Commit 30cb1371e39accf566d309905b7938fb4065b16c

Authored by Erickson Silva
2 parents c7bf37c8 1d486c40
Exists in master

Merge branch 'devel'

data/preposicoes.csv
... ... @@ -14,4 +14,6 @@ pela
14 14 pelos
15 15 pelas
16 16 ao
17   -aos
18 17 \ No newline at end of file
  18 +aos
  19 +às
  20 +a
19 21 \ No newline at end of file
... ...
install/linux/install.sh
... ... @@ -30,7 +30,7 @@ read -r -p "Deseja fazer o download das dependências? [Y/n] " response
30 30 echo -e "# Instalando dependências...\n"
31 31 sudo apt-get update
32 32 sudo apt-get install -y python-dev python-setuptools python-pip python-yaml python-numpy python-matplotlib
33   - sudo pip install nltk nltk_tgrep --upgrade
  33 + sudo pip install nltk==3.0.5 nltk_tgrep --upgrade
34 34  
35 35 fi
36 36  
... ...
src/AplicaRegras.py
... ... @@ -6,7 +6,6 @@
6 6  
7 7 #LAViD - Laboratório de Aplicações de Vídeo Digital
8 8  
9   -import platform
10 9 import re
11 10 import xml.etree.ElementTree as ET
12 11 from os.path import expanduser
... ... @@ -38,12 +37,10 @@ class AplicaRegras(object):
38 37 # Gera arvore a partir do arquivos regras.xml
39 38 def get_root(self):
40 39 '''Verifica qual o SO e gera o path de onde se encontra o diretório data.
41   - '''
42   - if "TRANSLATE_DATA" in environ:
  40 + '''
  41 + if "TRANSLATE_DATA" in environ:
43 42 arq_regras = path.join(environ.get("TRANSLATE_DATA"), "regras.xml")
44 43 return ET.parse(arq_regras).getroot()
45   - elif platform.system() == 'Windows':
46   - return ET.parse(environ.get("HOMEDRIVE")+'\\vlibras-libs\\vlibras-translate\data\\regras.xml').getroot()
47 44 return ET.parse(expanduser("~")+'/vlibras-translate/data/regras.xml').getroot()
48 45  
49 46 # Aplica regras morfológicas apartir do arquivo regras.xml
... ... @@ -264,8 +261,15 @@ class AplicaRegras(object):
264 261 # EU FELIZ PASSADO -> EU FELIZ
265 262 if morfo[i] is not None and morfo[i][1] == "NTK" and morfo[i][0]:
266 263 new_node = self.gerar_no(morfo[i])
267   - arvore[lista_pos_arv[i-1][:-3]].insert(2, new_node)
268   - #arvore[lista_pos_arv[i-1][:-2]].insert(2, new_node)
  264 +
  265 + #arvore[lista_pos_arv[i-1][:-3]].insert(2, new_node)
  266 + #arvore[lista_pos_arv[i-1][:-3]].insert(2, new_node)
  267 +
  268 + if str(arvore[lista_pos_arv[i-1][:-3]]).count('(') > 7:
  269 + arvore[lista_pos_arv[i-1][:-2]].insert(2, new_node)
  270 + else:
  271 + arvore[lista_pos_arv[i-1][:-3]].insert(2, new_node)
  272 +
269 273 try:
270 274 lista_pos_arv.insert(i,lista_pos_arv[i])
271 275 except:
... ... @@ -399,9 +403,14 @@ class AplicaRegras(object):
399 403 tag = it.get_ticket()
400 404  
401 405 if tag == "NUM":
  406 + try:
  407 + num_romano = roman_to_int(it.get_word().encode('utf-8'))
  408 + lista_simplificada[it.get_count()] = [num_romano.decode('utf-8'), 'NUM-R']
  409 + except:
  410 + pass
402 411 num = True
403 412  
404   - if tag[-2:] == "-P" and self.verificar_excecao_plural(it.get_word()):
  413 + if tag != "NPR-P" and tag[-2:] == "-P" or tag[-2:] == "_P" and self.verificar_excecao_plural(it.get_word()):
405 414 singular = self.analisar_plural(it.get_word())
406 415 lista_simplificada[it.get_count()][0] = singular
407 416  
... ... @@ -438,7 +447,7 @@ class AplicaRegras(object):
438 447 return token[:-2]+"l"
439 448 return token
440 449 elif(token[-1] == "s"):
441   - #TODO: Palavras paroxítonas ou proparoxítonas terminadas em S. Ex: lápis, vírus, tagênis, ônibus, etc
  450 + #TODO: Palavras paroxítonas ou proparoxítonas terminadas em S. Ex: lápis, vírus, tagênis, ônibus, etc
442 451 return token[:-1]
443 452 else:
444 453 return token
... ...
src/AplicaSinonimos.py
... ... @@ -27,26 +27,10 @@ class AplicaSinonimos(object):
27 27 '''Percorre a lista fazendo a substituição pelos sinonimos.
28 28 '''
29 29 lista_corrigida = []
30   - palavras_compostas = self.carregar_palavras_compostas()
31 30 for tupla in lista_anotada:
32 31 sinonimo = self.verificar_sinonimo(tupla[0])
33   - try:
34   - token_composto_2 = lista_corrigida[-1] + "_" + sinonimo
35   - token_composto_3 = lista_corrigida[-2] + "_" + lista_corrigida[-1] + "_" + sinonimo
36   - if token_composto_2.upper() in palavras_compostas:
37   - lista_corrigida[-1] = token_composto_2
38   - elif token_composto_3.upper() in palavras_compostas:
39   - lista_corrigida.pop()
40   - lista_corrigida[-1] = token_composto_3
41   - else:
42   - lista_corrigida.append(sinonimo)
43   - except IndexError:
44   - lista_corrigida.append(sinonimo)
45   -
46   - try:
47   - return " ".join(lista_corrigida)
48   - except:
49   - return " ".join([str(x[0]) for x in lista_anotada])
  32 + lista_corrigida.append(sinonimo)
  33 + return self.verificar_palavra_composta(lista_corrigida)
50 34  
51 35 # Verifica se há sinonimo do token
52 36 def verificar_sinonimo(self, token):
... ... @@ -56,13 +40,23 @@ class AplicaSinonimos(object):
56 40 return self.dicionarios.get_sinonimo(token)
57 41 return token
58 42  
  43 + def verificar_palavra_composta(self, lista):
  44 + palavras_compostas = self.carregar_palavras_compostas()
  45 + try:
  46 + sentenca_corrigida = "_".join(lista).upper()
  47 + except:
  48 + sentenca_corrigida = "_".join([str(x[0]) for x in lista]).upper()
  49 +
  50 + for p in palavras_compostas:
  51 + if p in sentenca_corrigida:
  52 + sentenca_corrigida = sentenca_corrigida.replace(p, p.replace("_", "#*#"))
  53 + return sentenca_corrigida.replace("_", " ").replace("#*#", "_")
  54 +
59 55 def carregar_palavras_compostas(self):
60 56 path = self.localizar_arquivo_palavras_compostas()
61 57 return set(open(path).read().decode('utf-8').split())
62 58  
63 59 def localizar_arquivo_palavras_compostas(self):
64   - if platform.system() == 'Windows':
65   - return environ.get("HOMEDRIVE")+'\\vlibras-libs\\vlibras-translate\data\\palavras_compostas.csv'
66   - elif "TRANSLATE_DATA" in environ:
  60 + if "TRANSLATE_DATA" in environ:
67 61 return path.join(environ.get("TRANSLATE_DATA"), "palavras_compostas.csv")
68 62 return expanduser("~")+'/vlibras-translate/data/palavras_compostas.csv'
69 63 \ No newline at end of file
... ...
src/ClassificaSentencas.py 0 → 100644
... ... @@ -0,0 +1,165 @@
  1 +#! /usr/bin/env python2.6
  2 +# -*- coding: utf-8 -*-
  3 +
  4 +#---------------------------------
  5 +
  6 +# Editado:
  7 +
  8 +#Autor: Erickson Silva
  9 +#Email: <erickson.silva@lavid.ufpb.br> <ericksonsilva@live.com>
  10 +
  11 +#LAViD - Laboratório de Aplicações de Vídeo Digital
  12 +
  13 +#---------------------------------
  14 +
  15 +
  16 +# Donatus Brazilian Portuguese Parser
  17 +#
  18 +# Copyright (C) 2010-2013 Leonel F. de Alencar
  19 +#
  20 +# Author: Leonel F. de Alencar <leonel.de.alencar@ufc.br>
  21 +# Homepage: <http://www.leonel.profusehost.net/>
  22 +#
  23 +# Project's URL: <http://sourceforge.net/projects/donatus/>
  24 +# For license information, see LICENSE.TXT
  25 +#
  26 +# $Id: alexp.py $
  27 +
  28 +"""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.
  29 +"""
  30 +import re,nltk, time, random
  31 +from os.path import expanduser
  32 +from os import environ, path
  33 +from Aelius.Extras import carrega
  34 +from Aelius import AnotaCorpus, Toqueniza
  35 +from unicodedata import normalize
  36 +
  37 +
  38 +class ClassificaSentencas(object):
  39 +
  40 + def __init__(self):
  41 + self.sentenca_anotada = ""
  42 + self.sleep_times = [0.1,0.2]
  43 +
  44 + def toqueniza(self, s):
  45 + """Decodifica string utilizando utf-8, retornando uma lista de tokens em unicode.
  46 + """
  47 + regex = re.compile('[%s]' % re.escape('“”'))
  48 + regex2 = re.compile('[%s]' % re.escape('«»'))
  49 + try:
  50 + decodificada = regex2.sub('',regex.sub('"',s.replace("–", "-").replace("—", "-"))).decode("utf-8")
  51 + except:
  52 + decodificada = s.decode("utf-8")
  53 + return Toqueniza.TOK_PORT.tokenize(decodificada)
  54 +
  55 + def obter_classificacao_morfologica(self):
  56 + return self.sentenca_anotada
  57 +
  58 + def etiqueta_sentenca(self, s):
  59 + """Aplica um dos etiquetadores do Aelius na etiquetagem da sentença dada como lista de tokens.
  60 + """
  61 + etiquetador = carrega("AeliusHunPos")
  62 + anotada = AnotaCorpus.anota_sentencas([s],etiquetador,"hunpos")[0]
  63 + while (anotada[0][1] is None):
  64 + time.sleep(random.choice(sleep_times))
  65 + anotada = AnotaCorpus.anota_sentencas([s],etiquetador,"hunpos")[0]
  66 + regex = re.compile('[%s]' % re.escape('!"#&\'()*+,-./:;<=>?@[\\]^_`{|}~'))
  67 + tag_punctuation = [".",",","QT","("]
  68 + anotada_corrigida = []
  69 + for x in anotada:
  70 + if x[1] not in tag_punctuation:
  71 + if x[1] == "NUM":
  72 + try:
  73 + float(x[0].replace(',', '.'))
  74 + anotada_corrigida.append(x)
  75 + continue
  76 + except:
  77 + pass
  78 +
  79 + tupla = [regex.sub('',x[0]).lower(),x[1]]
  80 + if tupla[0] != "": anotada_corrigida.append(tupla)
  81 + else:
  82 + if x[0] == ".":
  83 + anotada_corrigida.append(["[ponto]".decode("utf-8"),"SPT"])
  84 + elif x[0] == "?":
  85 + anotada_corrigida.append(["[interrogacao]".decode("utf-8"),"SPT"])
  86 + elif x[0] == "!":
  87 + anotada_corrigida.append(["[exclamacao]".decode("utf-8"),"SPT"])
  88 + return anotada_corrigida
  89 +
  90 + def gera_entradas_lexicais(self, lista):
  91 + """Gera entradas lexicais no formato CFG do NLTK a partir de lista de pares constituídos de tokens e suas etiquetas.
  92 + """
  93 + entradas=[]
  94 + for e in lista:
  95 + # é necessário substituir símbolos como "-" e "+" do CHPTB
  96 + # que não são aceitos pelo NLTK como símbolos não terminais
  97 + c=re.sub(r"[-+]","_",e[1])
  98 + c=re.sub(r"\$","_S",c)
  99 + entradas.append("%s -> '%s'" % (c, self.remove_acento(e[0])))
  100 + return entradas
  101 +
  102 + def corrige_anotacao(self, lista):
  103 + """Esta função deverá corrigir alguns dos erros de anotação mais comuns do Aelius. No momento, apenas é corrigida VB-AN depois de TR.
  104 + """
  105 + i=1
  106 + while i < len(lista):
  107 + if lista[i][1] == "VB-AN" and lista[i-1][1].startswith("TR"):
  108 + lista[i]=(lista[i][0],"VB-PP")
  109 + i+=1
  110 +
  111 + def encontra_arquivo(self):
  112 + """Encontra arquivo na pasta vlibras-translate.
  113 + """
  114 + if "TRANSLATE_DATA" in environ:
  115 + return path.join(environ.get("TRANSLATE_DATA"), "cfg.syn.nltk")
  116 + return expanduser("~") + "/vlibras-translate/data/cfg.syn.nltk"
  117 +
  118 + def extrai_sintaxe(self):
  119 + """Extrai gramática armazenada em arquivo cujo caminho é definido relativamente ao diretório nltk_data.
  120 + """
  121 + arquivo = self.encontra_arquivo()
  122 + if arquivo:
  123 + f=open(arquivo,"rU")
  124 + sintaxe=f.read()
  125 + f.close()
  126 + return sintaxe
  127 + else:
  128 + print "Arquivo %s não encontrado em nenhum dos diretórios de dados do NLTK:\n%s" % (caminho,"\n".join(nltk.data.path))
  129 +
  130 + def analisa_sentenca(self, sentenca):
  131 + """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.
  132 + """
  133 + parser = self.constroi_analisador(sentenca)
  134 + codificada=[]
  135 + for t in self.sentenca_anotada:
  136 + if t[1] != "SPT":
  137 + codificada.append(self.remove_acento(t[0]).encode("utf-8"))
  138 + trees=parser.parse_one(codificada)
  139 + return trees
  140 +
  141 + def constroi_analisador(self, s):
  142 + """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.
  143 + """
  144 + self.sentenca_anotada = self.etiqueta_sentenca(s)
  145 + self.corrige_anotacao(self.sentenca_anotada)
  146 + entradas = self.gera_entradas_lexicais(self.sentenca_anotada)
  147 + lexico="\n".join(entradas)
  148 + gramatica="%s\n%s" % (self.extrai_sintaxe().strip(),lexico)
  149 + cfg=nltk.CFG.fromstring(gramatica)
  150 + return nltk.ChartParser(cfg)
  151 +
  152 + def remove_acento(self, texto):
  153 + try:
  154 + return normalize('NFKD', texto.encode('utf-8').decode('utf-8')).encode('ASCII', 'ignore')
  155 + except:
  156 + return normalize('NFKD', texto.encode('iso-8859-1').decode('iso-8859-1')).encode('ASCII','ignore')
  157 +
  158 + def exibe_arvores(self, arvores):
  159 + """Função 'wrapper' para a função de exibição de árvores do NLTK"""
  160 + nltk.draw.draw_trees(*arvores)
  161 +
  162 + def iniciar_classificacao(self, sentenca):
  163 + tokens = self.toqueniza(sentenca)
  164 + tree = self.analisa_sentenca(tokens)
  165 + return tree
0 166 \ No newline at end of file
... ...
src/ConverteExtenso.py
... ... @@ -25,7 +25,45 @@ ext = [{&quot;um&quot;:&quot;1&quot;, &quot;dois&quot;:&quot;2&quot;, &quot;tres&quot;:&quot;3&quot;, &quot;quatro&quot;:&quot;4&quot;, &quot;cinco&quot;:&quot;5&quot;, &quot;seis&quot;:&quot;6&quot;,
25 25 und = {"mil":1000, "milhao":1000000, "bilhao":1000000000, "trilhao":1000000000000}
26 26 unds = {"mil":"000", "milhao":"000000","milhoes":"000000", "bilhao":"000000000","bilhoes":"000000000", "trilhao":"000000000000", "trilhoes":"000000000000"}
27 27  
28   -
  28 +def int_to_roman(input):
  29 + if not isinstance(input, type(1)):
  30 + raise TypeError, "expected integer, got %s" % type(input)
  31 + if not 0 < input < 4000:
  32 + raise ValueError, "Argument must be between 1 and 3999"
  33 + ints = (1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1)
  34 + nums = ('M', 'CM', 'D', 'CD','C', 'XC','L','XL','X','IX','V','IV','I')
  35 + result = []
  36 +
  37 + for i in range(len(ints)):
  38 + count = int(input / ints[i])
  39 + result.append(nums[i] * count)
  40 + input -= ints[i] * count
  41 + return ''.join(result)
  42 +
  43 +def roman_to_int(input):
  44 + if not isinstance(input, type("")):
  45 + raise TypeError, "expected string, got %s" % type(input)
  46 + input = input.upper( )
  47 + nums = {'M':1000,
  48 + 'D':500,
  49 + 'C':100,
  50 + 'L':50,
  51 + 'X':10,
  52 + 'V':5,
  53 + 'I':1}
  54 + sum = 0
  55 + for i in range(len(input)):
  56 + try:
  57 + value = nums[input[i]]
  58 + if i+1 < len(input) and nums[input[i+1]] > value:
  59 + sum -= value
  60 + else: sum += value
  61 + except KeyError:
  62 + raise ValueError, 'input is not a valid Roman numeral: %s' % input
  63 +
  64 + if int_to_roman(sum) == input: return str(sum)
  65 + else:
  66 + raise ValueError, 'input is not a valid Roman numeral: %s' % input
29 67  
30 68 def oneDigit(x):
31 69 return ext[0][x]
... ...
src/LerDicionarios.py
... ... @@ -8,20 +8,20 @@
8 8  
9 9 import os
10 10 import csv
11   -import platform
12 11  
13   -class Singleton(object):
  12 +class Singleton(type):
14 13 ''' Permite a criação de apenas uma instância da classe
15 14 '''
  15 + _instances = {}
  16 + def __call__(cls, *args, **kwargs):
  17 + if cls not in cls._instances:
  18 + cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
  19 + return cls._instances[cls]
16 20  
17   - def __new__(cls, *args, **kwargs):
18   - if '_inst' not in vars(cls):
19   - cls._inst = object.__new__(cls, *args, **kwargs)
20   - return cls._inst
21   -
22   -class LerDicionarios(Singleton):
  21 +class LerDicionarios(object):
23 22 '''Carrega todos os arquivos (dicionários) necessários para auxiliar durante o processo de tradução.
24 23 '''
  24 + __metaclass__ = Singleton
25 25  
26 26 def __init__(self):
27 27 self.path = self.get_path()
... ... @@ -37,31 +37,13 @@ class LerDicionarios(Singleton):
37 37 self.set_vb_ligacao = []
38 38 self.dic_vb_muda_negacao = []
39 39 self.file = ''
40   - self.carregar_dicionarios()
41 40  
42 41 def get_path(self):
43 42 '''Verifica qual o SO e gera o path de onde se encontra o diretório data.
44 43 '''
45 44 if "TRANSLATE_DATA" in os.environ:
46 45 return os.environ.get("TRANSLATE_DATA")
47   - elif platform.system() == 'Windows':
48   - return os.environ.get("HOMEDRIVE") + "\\vlibras-libs\\vlibras-translate\data\\"
49   - return os.path.expanduser("~") + "/vlibras-translate/data"
50   -
51   - def carregar_dicionarios(self):
52   - '''Realiza a leitura dos arquivos e atribui à estruturas de dicionários e sets.
53   - '''
54   - self.carregar_excecoes_plural()
55   - self.carregar_adverbios_intensidade()
56   - self.carregar_adverbios_tempo()
57   - self.carregar_artigos()
58   - self.carregar_preposicoes()
59   - self.carregar_sinonimos()
60   - self.carregar_subs_2_generos()
61   - self.carregar_pronomes_tratamento()
62   - self.carregar_verbos_infinitivo()
63   - self.carregar_verbos_ligacao()
64   - self.carregar_verbos_muda_negacao
  46 + return os.path.expanduser("~") + "/vlibras-translate/data"
65 47  
66 48 def montar_diretorio(self, arquivo):
67 49 return os.path.join(self.path, arquivo)
... ... @@ -225,74 +207,104 @@ class LerDicionarios(Singleton):
225 207 def has_excecao_plural(self, token):
226 208 '''Verifica se o token recebido consta no arquivo de exceções de plural.
227 209 '''
  210 + if not self.set_exc_plural:
  211 + self.carregar_excecoes_plural()
228 212 return token not in self.set_exc_plural
229 213  
230 214 def has_adverbio_intensidade(self, token):
231 215 '''Verifica se o token recebido consta no arquivo de advérbios de intensidade.
232 216 '''
  217 + if not self.dic_adv_intensidade:
  218 + self.carregar_adverbios_intensidade()
233 219 return self.dic_adv_intensidade.has_key(token)
234 220  
235 221 def has_adverbio_tempo(self, token):
236 222 '''Verifica se o token recebido consta no arquivo de advérbios de tempo.
237 223 '''
  224 + if not self.set_adv_tempo:
  225 + self.carregar_adverbios_tempo()
238 226 return token in self.set_adv_tempo
239 227  
240 228 def has_artigo(self, token):
241 229 '''Verifica se o token recebido consta no arquivo de artigos a serem removidos.
242 230 '''
  231 + if not self.set_art:
  232 + self.carregar_artigos()
243 233 return token in self.set_art
244 234  
245 235 def has_preposicao(self, token):
246 236 '''Verifica se o token recebido consta no arquivo de preposições a serem removidas.
247 237 '''
  238 + if not self.set_prep:
  239 + self.carregar_preposicoes()
248 240 return token in self.set_prep
249 241  
250 242 def has_sinonimo(self, token):
251 243 '''Verifica se o token recebido consta no arquivo de sinonimos.
252 244 '''
  245 + if not self.dic_sin:
  246 + self.carregar_sinonimos()
253 247 return self.dic_sin.has_key(token)
254 248  
255 249 def has_pron_tratam(self, token):
256 250 '''Verifica se o token recebido consta no arquivo de pronomes de tratamento.
257 251 '''
  252 + if not self.set_pron_trat:
  253 + self.carregar_pronomes_tratamento()
258 254 return token in self.set_pron_trat
259 255  
260 256 def has_subst_2_generos (self, token):
261 257 '''Verifica se o token recebido consta no arquivo de substantivos comuns de 2 generos.
262 258 '''
  259 + if not self.set_sb_2_gen:
  260 + self.carregar_subs_2_generos()
263 261 return token in self.set_sb_2_gen
264 262  
265 263 def has_verbo_infinitivo(self, token):
266 264 '''Verifica se o token recebido consta no arquivo de verbos no infinitivo.
267 265 '''
  266 + if not self.dic_vb_infinitivo:
  267 + self.carregar_verbos_infinitivo()
268 268 return self.dic_vb_infinitivo.has_key(token)
269 269  
270 270 def has_verbo_ligacao(self, token):
271 271 '''Verifica se o token recebido consta no arquivo de verbos de ligação.
272 272 '''
  273 + if not self.set_vb_ligacao:
  274 + self.carregar_verbos_ligacao()
273 275 return token in self.set_vb_ligacao
274 276  
275 277 def has_verbo_muda_negacao(self, token):
276 278 '''Verifica se o token recebido consta no arquivo de verbos que mudam de negação.
277 279 '''
  280 + if not self.dic_vb_muda_negacao:
  281 + self.carregar_verbos_muda_negacao()
278 282 return self.dic_vb_muda_negacao.has_key(token)
279 283  
280 284 def get_adverbio_intensidade(self, token):
281 285 '''Verifica se o token recebido consta no arquivo de advérbios de intensidade.
282 286 '''
  287 + if not self.dic_adv_intensidade:
  288 + self.carregar_adverbios_intensidade()
283 289 return self.dic_adv_intensidade[token]
284 290  
285 291 def get_sinonimo(self, token):
286 292 '''Obtém o sinônimo do token.
287 293 '''
  294 + if not self.dic_sin:
  295 + self.carregar_sinonimos()
288 296 return self.dic_sin[token]
289 297  
290 298 def get_verbo_infinitivo(self, token):
291 299 '''Obtém o verbo no infinitivo do token.
292 300 '''
  301 + if not self.dic_vb_infinitivo:
  302 + self.carregar_verbos_infinitivo()
293 303 return self.dic_vb_infinitivo[token]
294 304  
295 305 def get_verbo_muda_negacao(self, token):
296 306 '''Obtém o verbo que muda a negação do token.
297 307 '''
  308 + if not self.dic_vb_muda_negacao:
  309 + self.carregar_verbos_muda_negacao()
298 310 return self.dic_vb_muda_negacao[token]
299 311 \ No newline at end of file
... ...
src/PortGlosa.py
... ... @@ -11,22 +11,20 @@ from ThreadTradutor import *
11 11 from TraduzSentencas import *
12 12 from LerDicionarios import *
13 13  
14   -
15 14 tradutor = TraduzSentencas()
16   -dicionario = LerDicionarios()
17 15 taxas = []
18 16  
19 17 def traduzir(texto, log=None, threads=False, taxa_qualidade=False):
20   - tradutor.set_level(log) if log != None else tradutor.desativar_logging()
  18 + #tradutor.set_level(log) if log != None else tradutor.desativar_logging()
21 19 if texto.isspace() or texto == "":
22 20 #or not checar_idioma(texto):
23 21 return "ESCOLHER TEXTO CERTO"
24 22  
25   - elif threads:
26   - return iniciar_com_threads(texto, taxa_qualidade)
  23 + #elif threads:
  24 + # return iniciar_com_threads(texto, taxa_qualidade)
27 25  
28   - else:
29   - return iniciar_sem_threads(texto, taxa_qualidade)
  26 + #else:
  27 + return iniciar_sem_threads(texto, taxa_qualidade)
30 28  
31 29 def iniciar_com_threads(texto, taxa_qualidade):
32 30 texto_quebrado = quebrar_texto(texto)
... ... @@ -64,6 +62,7 @@ def quebrar_texto(texto):
64 62 if '.' not in texto:
65 63 return [texto]
66 64  
  65 + dicionario = LerDicionarios()
67 66 texto_quebrado = texto.split()
68 67 tamanho_texto_quebrado = len(texto_quebrado)
69 68 sentencas = []
... ...
src/TraduzSentencas.py
... ... @@ -6,7 +6,7 @@
6 6  
7 7 #LAViD - Laboratório de Aplicações de Vídeo Digital
8 8  
9   -import alexp
  9 +from ClassificaSentencas import *
10 10 from AplicaRegras import *
11 11 from AplicaSinonimos import *
12 12 import logging
... ... @@ -24,6 +24,7 @@ class TraduzSentencas(object):
24 24 def __init__(self):
25 25 '''Instancia os aplicadores de regras e sinônimos.
26 26 '''
  27 + self.classificador = ClassificaSentencas()
27 28 self.aplic_regras = AplicaRegras()
28 29 self.aplic_sin = AplicaSinonimos()
29 30 self.check_level()
... ... @@ -33,13 +34,13 @@ class TraduzSentencas(object):
33 34 '''
34 35 try:
35 36 has_sintatica = True
36   - analise_sintatica = alexp.run(sentenca)
  37 + analise_sintatica = self.classificador.iniciar_classificacao(sentenca)
37 38 except Exception as ex:
38 39 self.salvar_log(str(traceback.format_exc()))
39 40 analise_sintatica = None
40 41 has_sintatica = False
41 42  
42   - analise_morfologica = alexp.getAnaliseMorfologica()
  43 + analise_morfologica = self.classificador.obter_classificacao_morfologica()
43 44  
44 45 if (isinstance(analise_sintatica,type(None))):
45 46 regras_aplicadas = self.aplic_regras.aplicar_regras_morfo(analise_morfologica)
... ...
src/alexp.py
... ... @@ -1,156 +0,0 @@
1   -#! /usr/bin/env python2.6
2   -# -*- coding: utf-8 -*-
3   -
4   -#---------------------------------
5   -
6   -# Editado:
7   -
8   -#Autor: Erickson Silva
9   -#Email: <erickson.silva@lavid.ufpb.br> <ericksonsilva@live.com>
10   -
11   -#LAViD - Laboratório de Aplicações de Vídeo Digital
12   -
13   -#---------------------------------
14   -
15   -
16   -# Donatus Brazilian Portuguese Parser
17   -#
18   -# Copyright (C) 2010-2013 Leonel F. de Alencar
19   -#
20   -# Author: Leonel F. de Alencar <leonel.de.alencar@ufc.br>
21   -# Homepage: <http://www.leonel.profusehost.net/>
22   -#
23   -# Project's URL: <http://sourceforge.net/projects/donatus/>
24   -# For license information, see LICENSE.TXT
25   -#
26   -# $Id: alexp.py $
27   -
28   -"""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.
29   -"""
30   -import re,nltk,platform, time, random
31   -from os.path import expanduser
32   -from os import environ, path
33   -from Aelius.Extras import carrega
34   -from Aelius import AnotaCorpus
35   -from unicodedata import normalize
36   -
37   -sentenca_anotada=""
38   -sleep_times=[0.1,0.2]
39   -
40   -def toqueniza(s):
41   - """Decodifica string utilizando utf-8, retornando uma lista de tokens em unicode.
42   - """
43   - regex = re.compile('[%s]' % re.escape('“”'))
44   - decodificada=regex.sub('"',s.replace("–", "-").replace("—", "-")).decode("utf-8")
45   - return AnotaCorpus.TOK_PORT.tokenize(decodificada)
46   -
47   -def getAnaliseMorfologica():
48   - return sentenca_anotada
49   -
50   -def etiquetaSentenca(s):
51   - """Aplica um dos etiquetadores do Aelius na etiquetagem da sentença dada como lista de tokens.
52   - """
53   - etiquetador = carrega("AeliusHunPos")
54   - anotada = AnotaCorpus.anota_sentencas([s],etiquetador,"hunpos")[0]
55   - while (anotada[0][1] is None):
56   - time.sleep(random.choice(sleep_times))
57   - anotada = AnotaCorpus.anota_sentencas([s],etiquetador,"hunpos")[0]
58   - regex = re.compile('[%s]' % re.escape('!"#&\'()*+,-./:;<=>?@[\\]^_`{|}~'))
59   - tag_punctuation = [".",",","QT","("]
60   - anotada_corrigida = []
61   - for x in anotada:
62   - if x[1] not in tag_punctuation:
63   - if x[1] == "NUM":
64   - anotada_corrigida.append(x)
65   - continue
66   - tupla = [regex.sub('',x[0]).lower(),x[1]]
67   - if tupla[0] != "": anotada_corrigida.append(tupla)
68   - else:
69   - if x[0] == ".":
70   - anotada_corrigida.append(["[ponto]".decode("utf-8"),"SPT"])
71   - elif x[0] == "?":
72   - anotada_corrigida.append(["[interrogacao]".decode("utf-8"),"SPT"])
73   - elif x[0] == "!":
74   - anotada_corrigida.append(["[exclamacao]".decode("utf-8"),"SPT"])
75   - return anotada_corrigida
76   -
77   -def geraEntradasLexicais(lista):
78   - """Gera entradas lexicais no formato CFG do NLTK a partir de lista de pares constituídos de tokens e suas etiquetas.
79   - """
80   - entradas=[]
81   - for e in lista:
82   - # é necessário substituir símbolos como "-" e "+" do CHPTB
83   - # que não são aceitos pelo NLTK como símbolos não terminais
84   - c=re.sub(r"[-+]","_",e[1])
85   - c=re.sub(r"\$","_S",c)
86   - entradas.append("%s -> '%s'" % (c, removeAcento(e[0])))
87   - return entradas
88   -
89   -def corrigeAnotacao(lista):
90   - """Esta função deverá corrigir alguns dos erros de anotação mais comuns do Aelius. No momento, apenas é corrigida VB-AN depois de TR.
91   - """
92   - i=1
93   - while i < len(lista):
94   - if lista[i][1] == "VB-AN" and lista[i-1][1].startswith("TR"):
95   - lista[i]=(lista[i][0],"VB-PP")
96   - i+=1
97   -
98   -def encontraArquivo():
99   - """Encontra arquivo na pasta vlibras-translate.
100   - """
101   - so = platform.system()
102   - if "TRANSLATE_DATA" in environ:
103   - return path.join(environ.get("TRANSLATE_DATA"), "cfg.syn.nltk")
104   - elif so == 'Windows':
105   - return environ.get("HOMEDRIVE") + "\\vlibras-libs\\vlibras-translate\data\cfg.syn.nltk"
106   - return expanduser("~") + "/vlibras-translate/data/cfg.syn.nltk"
107   -
108   -def extraiSintaxe():
109   - """Extrai gramática armazenada em arquivo cujo caminho é definido relativamente ao diretório nltk_data.
110   - """
111   - arquivo=encontraArquivo()
112   - if arquivo:
113   - f=open(arquivo,"rU")
114   - sintaxe=f.read()
115   - f.close()
116   - return sintaxe
117   - else:
118   - print "Arquivo %s não encontrado em nenhum dos diretórios de dados do NLTK:\n%s" % (caminho,"\n".join(nltk.data.path))
119   -
120   -def analisaSentenca(sentenca):
121   - """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.
122   - """
123   - parser=constroiAnalisador(sentenca)
124   - codificada=[]
125   - for t in sentenca_anotada:
126   - if t[1] != "SPT":
127   - codificada.append(removeAcento(t[0]).encode("utf-8"))
128   - trees=parser.parse_one(codificada)
129   - return trees
130   -
131   -def constroiAnalisador(s):
132   - """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.
133   - """
134   - global sentenca_anotada
135   - sentenca_anotada=etiquetaSentenca(s)
136   - corrigeAnotacao(sentenca_anotada)
137   - entradas=geraEntradasLexicais(sentenca_anotada)
138   - lexico="\n".join(entradas)
139   - gramatica="%s\n%s" % (extraiSintaxe().strip(),lexico)
140   - cfg=nltk.CFG.fromstring(gramatica)
141   - return nltk.ChartParser(cfg)
142   -
143   -def removeAcento(texto):
144   - try:
145   - return normalize('NFKD', texto.encode('utf-8').decode('utf-8')).encode('ASCII', 'ignore')
146   - except:
147   - return normalize('NFKD', texto.encode('iso-8859-1').decode('iso-8859-1')).encode('ASCII','ignore')
148   -
149   -def exibeArvores(arvores):
150   - """Função 'wrapper' para a função de exibição de árvores do NLTK"""
151   - nltk.draw.draw_trees(*arvores)
152   -
153   -def run(sentenca):
154   - tokens=toqueniza(sentenca)
155   - tree=analisaSentenca(tokens)
156   - return tree
157 0 \ No newline at end of file