Commit d42044c486532763190da438028c558d18bed44c
1 parent
ff7863f2
Exists in
master
and in
1 other branch
Altera alexp para aceitar acentuação na sentença
Showing
1 changed file
with
38 additions
and
17 deletions
Show diff stats
src/new/alexp.py
... | ... | @@ -31,15 +31,11 @@ import re, string,nltk,platform |
31 | 31 | from os.path import expanduser |
32 | 32 | from Aelius.Extras import carrega |
33 | 33 | from Aelius import AnotaCorpus |
34 | +from nltk_tgrep import tgrep_positions, tgrep_nodes | |
35 | +from unicodedata import normalize | |
34 | 36 | |
35 | -# definição de algumas variáveis globais para | |
36 | -# facilitar utilização das diferentes funções do módulo | |
37 | 37 | |
38 | -# eventualmente será preciso incluir aqui outros sinais | |
39 | -# de pontuação, como o travessão | |
40 | -PUNCT=string.punctuation | |
41 | - | |
42 | -SENTENCA_ANOTADA="" | |
38 | +sentenca_anotada="" | |
43 | 39 | |
44 | 40 | |
45 | 41 | def toqueniza(s): |
... | ... | @@ -49,13 +45,14 @@ def toqueniza(s): |
49 | 45 | return AnotaCorpus.TOK_PORT.tokenize(decodificada) |
50 | 46 | |
51 | 47 | def getAnaliseMorfologica(): |
52 | - return SENTENCA_ANOTADA | |
48 | + return sentenca_anotada | |
53 | 49 | |
54 | 50 | def etiquetaSentenca(s): |
55 | 51 | """Aplica um dos etiquetadores do Aelius na etiquetagem da sentença dada como lista de tokens. |
56 | 52 | """ |
57 | 53 | etiquetador = carrega("AeliusHunPos") |
58 | 54 | anotada = AnotaCorpus.anota_sentencas([s],etiquetador,"hunpos")[0] |
55 | + anotada[0] = (anotada[0][0].lower(), anotada[0][1]) | |
59 | 56 | return anotada |
60 | 57 | |
61 | 58 | def geraEntradasLexicais(lista): |
... | ... | @@ -67,7 +64,7 @@ def geraEntradasLexicais(lista): |
67 | 64 | # que não são aceitos pelo NLTK como símbolos não terminais |
68 | 65 | c=re.sub(r"[-+]","_",e[1]) |
69 | 66 | c=re.sub(r"\$","_S",c) |
70 | - entradas.append("%s -> '%s'" % (c, e[0].lower())) | |
67 | + entradas.append("%s -> '%s'" % (c, removeAcento(e[0].lower()))) | |
71 | 68 | return entradas |
72 | 69 | |
73 | 70 | def corrigeAnotacao(lista): |
... | ... | @@ -101,33 +98,57 @@ def extraiSintaxe(): |
101 | 98 | return sintaxe |
102 | 99 | else: |
103 | 100 | print "Arquivo %s não encontrado em nenhum dos diretórios de dados do NLTK:\n%s" % (caminho,"\n".join(nltk.data.path)) |
104 | - | |
105 | 101 | |
106 | 102 | def analisaSentenca(sentenca): |
107 | 103 | """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. |
108 | 104 | """ |
109 | 105 | parser=constroiAnalisador(sentenca) |
110 | - codificada=[w.encode("utf-8") for w in sentenca] | |
106 | + codificada=[removeAcento(w).encode("utf-8") for w in sentenca] | |
111 | 107 | trees=parser.parse_one(codificada) |
112 | 108 | return trees |
113 | 109 | |
114 | 110 | def constroiAnalisador(s): |
115 | 111 | """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. |
116 | 112 | """ |
117 | - global SENTENCA_ANOTADA | |
118 | - SENTENCA_ANOTADA=etiquetaSentenca(s) | |
119 | - corrigeAnotacao(SENTENCA_ANOTADA) | |
120 | - entradas=geraEntradasLexicais(SENTENCA_ANOTADA) | |
113 | + global sentenca_anotada | |
114 | + sentenca_anotada=etiquetaSentenca(s) | |
115 | + corrigeAnotacao(sentenca_anotada) | |
116 | + entradas=geraEntradasLexicais(sentenca_anotada) | |
121 | 117 | lexico="\n".join(entradas) |
122 | 118 | gramatica="%s\n%s" % (extraiSintaxe().strip(),lexico) |
123 | 119 | cfg=nltk.CFG.fromstring(gramatica) |
124 | 120 | return nltk.ChartParser(cfg) |
125 | 121 | |
122 | +def corrigeArvore(arvore): | |
123 | + lista_pos_arv = [] | |
124 | + for tupla in sentenca_anotada: | |
125 | + string_grep = adaptaAnotacao(tupla[1]) + " < " + tupla[0].lower() | |
126 | + node = tgrep_positions(arvore, string_grep) | |
127 | + if not node: | |
128 | + string_grep = adaptaAnotacao(tupla[1]) + " < " + removeAcento(tupla[0].lower()) | |
129 | + node = tgrep_positions(arvore, string_grep) | |
130 | + if node[0] in lista_pos_arv: | |
131 | + node.reverse() | |
132 | + lista_pos_arv.append(node[0]) | |
133 | + for i in range(0, len(sentenca_anotada)): | |
134 | + if arvore[lista_pos_arv[i]][0] != sentenca_anotada[i][0]: | |
135 | + arvore[lista_pos_arv[i]][0] = sentenca_anotada[i][0] | |
136 | + return arvore | |
137 | + | |
138 | +def removeAcento(texto): | |
139 | + return normalize('NFKD', texto.encode('utf-8').decode('utf-8')).encode('ascii', 'ignore') | |
140 | + | |
141 | +def adaptaAnotacao(anotacao): | |
142 | + split = anotacao.split('_') | |
143 | + for i in range(0, len(split)): | |
144 | + split[i] = split[i].replace('-','_') | |
145 | + return "-".join(split) | |
146 | + | |
126 | 147 | def exibeArvores(arvores): |
127 | 148 | """Função 'wrapper' para a função de exibição de árvores do NLTK""" |
128 | 149 | nltk.draw.draw_trees(*arvores) |
129 | 150 | |
130 | 151 | def run(sentenca): |
131 | 152 | tokens=toqueniza(sentenca) |
132 | - trees=analisaSentenca(tokens) | |
133 | - return trees | |
134 | 153 | \ No newline at end of file |
154 | + tree=analisaSentenca(tokens) | |
155 | + return corrigeArvore(tree) | |
135 | 156 | \ No newline at end of file | ... | ... |