Commit 361e9a92c0e63ceb6a968b59ea25c36fcad2f624
1 parent
f56fda5a
Exists in
master
and in
1 other branch
Corrige aplicação de regras sintáticas
Showing
1 changed file
with
247 additions
and
208 deletions
Show diff stats
src/new/AplicaRegras.py
@@ -7,6 +7,7 @@ | @@ -7,6 +7,7 @@ | ||
7 | #LAViD - Laboratório de Aplicações de Vídeo Digital | 7 | #LAViD - Laboratório de Aplicações de Vídeo Digital |
8 | 8 | ||
9 | import platform | 9 | import platform |
10 | +import re | ||
10 | import xml.etree.ElementTree as ET | 11 | import xml.etree.ElementTree as ET |
11 | from os.path import expanduser | 12 | from os.path import expanduser |
12 | from collections import deque | 13 | from collections import deque |
@@ -19,114 +20,110 @@ from nltk import ParentedTree, Tree, draw | @@ -19,114 +20,110 @@ from nltk import ParentedTree, Tree, draw | ||
19 | 20 | ||
20 | class AplicaRegras(object): | 21 | class AplicaRegras(object): |
21 | 22 | ||
22 | - # inicializa todos as variaveis | ||
23 | def __init__(self): | 23 | def __init__(self): |
24 | self.__root = self.get_root() | 24 | self.__root = self.get_root() |
25 | self.dicionarios = LerDicionarios() | 25 | self.dicionarios = LerDicionarios() |
26 | + # Dicionário de funcões do campo specific do arquivo de regras | ||
26 | self.__especificos = {"advt":self.verificar_adv_tempo, "v":self.verificar_vb_infinitivo, "x":self.verificar_preposicao, | 27 | self.__especificos = {"advt":self.verificar_adv_tempo, "v":self.verificar_vb_infinitivo, "x":self.verificar_preposicao, |
27 | "c":self.verificar_subst_genero, "a":self.verificar_artigo, "l":self.verificar_vb_ligacao, | 28 | "c":self.verificar_subst_genero, "a":self.verificar_artigo, "l":self.verificar_vb_ligacao, |
28 | "i":self.verificar_adv_intensidade, "vbi":"zero", "n":self.verificar_vb_muda_negacao, "abmn":"zero", | 29 | "i":self.verificar_adv_intensidade, "vbi":"zero", "n":self.verificar_vb_muda_negacao, "abmn":"zero", |
29 | "adji":"zero","adjn":"zero", "advi":"zero"} | 30 | "adji":"zero","adjn":"zero", "advi":"zero"} |
30 | 31 | ||
32 | + self.__acoes = {"change_vb":self.get_vb_infinitivo, "concate_intens":self.get_token_intensidade} | ||
33 | + | ||
34 | + # Gera arvore a partir do arquivos regras.xml | ||
31 | def get_root(self): | 35 | def get_root(self): |
32 | if platform.system() == 'Windows': | 36 | if platform.system() == 'Windows': |
33 | return ET.parse(expanduser("~")+'\\vlibras-translate\data\\regras.xml').getroot() | 37 | return ET.parse(expanduser("~")+'\\vlibras-translate\data\\regras.xml').getroot() |
34 | return ET.parse(expanduser("~")+'/vlibras-translate/data/regras.xml').getroot() | 38 | return ET.parse(expanduser("~")+'/vlibras-translate/data/regras.xml').getroot() |
35 | 39 | ||
40 | + # Aplica regras morfológicas apartir do arquivo regras.xml | ||
36 | def aplicar_regras_morfo(self, lista, sint=False): | 41 | def aplicar_regras_morfo(self, lista, sint=False): |
37 | - self.lista = list(lista) | ||
38 | - self.quantidade_iter_pular = 0 | ||
39 | - self.lista_corrigida = [] | 42 | + self.lista = list(lista) # Nova cópia da lista morfológica |
43 | + self.lista_corrigida =[] # Lista morfológica após a aplicação das regras | ||
40 | 44 | ||
41 | it = Iterator() | 45 | it = Iterator() |
42 | it.load(self.lista) | 46 | it.load(self.lista) |
43 | 47 | ||
44 | - while(it.has_next()): | 48 | + while(it.has_next()): |
45 | for morpho in self.__root.findall('morphological'): | 49 | for morpho in self.__root.findall('morphological'): |
46 | - self.has_rule = False | ||
47 | - for rule in morpho.findall('rule'): # procura a tag rule | 50 | + self.has_rule = False # Boolean caso encontre encontre regra compativel |
51 | + for rule in morpho.findall('rule'): | ||
52 | + # Verifica se a regra está ativa e se o nome da regra, ou o ínicio, é igual a tag de classificação do token atual | ||
48 | if rule.find('active').text == "true" and rule.get('name').split("_")[0] == it.get_ticket(): | 53 | if rule.find('active').text == "true" and rule.get('name').split("_")[0] == it.get_ticket(): |
49 | count = int(rule.find('count').text) | 54 | count = int(rule.find('count').text) |
50 | - self.lista_iteracoes = [] | ||
51 | - if count == 1: | ||
52 | - self.lista_iteracoes = [it.get_token()] | ||
53 | - else: | ||
54 | - try: | ||
55 | - self.lista_iteracoes = it.get_interval(count) | ||
56 | - it.skip(count-1) | ||
57 | - except: | ||
58 | - continue | 55 | + self.lista_iteracoes = [] # Lista que conterá todas tuplas referentes a quantidade de classes da regra |
56 | + | ||
57 | + # Obtém o intervalo de tuplas de acordo com o número de classes da regra | ||
58 | + try: | ||
59 | + self.lista_iteracoes = it.get_interval(count) | ||
60 | + print '# LISTA DA ITERAÇÂO: ' | ||
61 | + print self.lista_iteracoes | ||
62 | + except: | ||
63 | + continue | ||
59 | 64 | ||
65 | + # Gera o nome da regra do intervalo de tuplas e verifica se é igual ao nome da regra em si | ||
60 | self.nome_regra = self.gerar_nome_regra(self.lista_iteracoes) | 66 | self.nome_regra = self.gerar_nome_regra(self.lista_iteracoes) |
61 | - if rule.get('name') == self.nome_regra: # verifica se a regra é aplicavel e a mesma esta ativa | 67 | + if rule.get('name') == self.nome_regra: |
62 | self.has_rule = True | 68 | self.has_rule = True |
63 | - self.lista_iteracao_regra = count * [None] | ||
64 | self.count_iteracao_regra = -1 | 69 | self.count_iteracao_regra = -1 |
65 | 70 | ||
66 | - print "REGRA MORFOLÓGICA: " + rule.get('name') | 71 | + print "REGRA MORFOLÓGICA ENCONTRADA: " + rule.get('name') |
67 | 72 | ||
73 | + self.lista_iteracao_regra = [] # Lista temporária | Insere tokens após a aplicação das regras | ||
74 | + | ||
68 | for classe in rule.iter('class'): # for nas tags class | 75 | for classe in rule.iter('class'): # for nas tags class |
69 | - | ||
70 | - title = classe.find('title') | ||
71 | - newpos = classe.find('newpos') | 76 | + action = classe.find('action') |
72 | newprop = classe.find('newprop') | 77 | newprop = classe.find('newprop') |
73 | newtoken = classe.find('newtoken') | 78 | newtoken = classe.find('newtoken') |
74 | newtokenpos = classe.find('newtokenpos') | 79 | newtokenpos = classe.find('newtokenpos') |
75 | - self.specific = classe.find('specific') | 80 | + specific = classe.find('specific') |
76 | 81 | ||
77 | self.count_iteracao_regra += 1 | 82 | self.count_iteracao_regra += 1 |
78 | tupla = self.lista_iteracoes[self.count_iteracao_regra] | 83 | tupla = self.lista_iteracoes[self.count_iteracao_regra] |
79 | 84 | ||
80 | - if self.specific is not None: | ||
81 | - self.specific = self.__especificos[self.specific.text](tupla[0]) | ||
82 | - if self.specific == False: | 85 | + if specific is not None: |
86 | + result_specific = self.__especificos[specific.text](tupla[0]) | ||
87 | + if result_specific is False: | ||
88 | + print "REGRA MORFOLÓGICA " + rule.get('name') + " INVÁLIDA. PROCURANDO OUTRA..." | ||
83 | self.has_rule = False | 89 | self.has_rule = False |
84 | - self.quantidade_iter_pular = 0 | ||
85 | break | 90 | break |
86 | 91 | ||
87 | - if newprop is not None and newtoken is not None: | ||
88 | - if newtokenpos is not None and newtokenpos.text == "0": | ||
89 | - self.lista_iteracao_regra[self.count_iteracao_regra] = (newtoken.text + "_" + self.specific, newprop.text) | ||
90 | - else: | ||
91 | - self.lista_iteracao_regra[self.count_iteracao_regra] = (self.specific + "_" + newtoken.text, newprop.text) | ||
92 | - continue | ||
93 | - | ||
94 | - elif newprop is not None: | ||
95 | - self.lista_iteracao_regra.append([self.specific,newprop.text]) | ||
96 | - | ||
97 | - if newtoken is not None and newpos is not None: | ||
98 | - if newtokenpos is not None: | ||
99 | - lista_merge = count * [None] | ||
100 | - lista_merge[int(newpos.text)] = tupla[0] | ||
101 | - lista_merge[int(newtokenpos.text)] = newtoken.text | ||
102 | - merge_tokens = "_".join(lista_merge) | ||
103 | - self.lista_iteracao_regra.append([merge_tokens, title.text]) | ||
104 | - else: | ||
105 | - self.lista_iteracao_regra.append([tupla[0] + "_" + newtoken.text, title.text]) | ||
106 | - | ||
107 | - elif newpos is not None: | ||
108 | - if newpos.text == "-1": | ||
109 | - self.lista_corrigida.append(None) | 92 | + if action is not None: |
93 | + action_text = action.text | ||
94 | + if action_text == "remove": | ||
95 | + self.lista_iteracao_regra.append(None) | ||
110 | continue | 96 | continue |
111 | - else: | ||
112 | - self.lista_iteracao_regra[int(newpos.text)] = tupla | ||
113 | - | ||
114 | - elif newtoken is not None: | ||
115 | - token_anterior = self.lista_iteracao_regra[self.count_iteracao_regra][0] | ||
116 | - ticket_anterior = self.lista_iteracao_regra[self.count_iteracao_regra][1] | ||
117 | - if newtokenpos is not None and newtokenpos.text == "0": | ||
118 | - self.lista_iteracao_regra[self.count_iteracao_regra] = [newtoken.text + "_" + token_anterior, ticket_anterior] | ||
119 | - else: | ||
120 | - self.lista_iteracao_regra[self.count_iteracao_regra] = [token_anterior + "_" + newtoken.text, ticket_anterior] | ||
121 | - | ||
122 | - if self.has_rule: | ||
123 | - self.lista_corrigida.append(filter(None, self.lista_iteracao_regra)[0]) | ||
124 | - break | ||
125 | - | ||
126 | - if (self.has_rule == False): | 97 | + elif action_text == "invert": |
98 | + self.lista_iteracao_regra.reverse() | ||
99 | + elif self.__acoes.has_key(action_text): | ||
100 | + result_action = self.__acoes[action_text](tupla[0]).lower() | ||
101 | + self.lista_iteracao_regra.append([result_action, tupla[1]]) | ||
102 | + else: | ||
103 | + self.lista_iteracao_regra.append(tupla) | ||
104 | + | ||
105 | + if newprop is not None: | ||
106 | + self.lista_iteracao_regra[self.count_iteracao_regra][1] = newprop.text | ||
107 | + | ||
108 | + if newtoken is not None: | ||
109 | + if newtokenpos.text == "next": | ||
110 | + self.lista_iteracao_regra.append([newtoken.text.lower(), "NTK"]) | ||
111 | + elif newtokenpos.text == "previous": | ||
112 | + self.lista_iteracao_regra.append(self.lista_iteracao_regra[-1]) | ||
113 | + self.lista_iteracao_regra[-2] = [newtoken.text.lower(), "NTK"] | ||
114 | + elif newtokenpos.text == "end": | ||
115 | + print "TODO" | ||
116 | + | ||
117 | + if self.has_rule: | ||
118 | + it.skip(count-1) | ||
119 | + self.lista_corrigida.extend(self.lista_iteracao_regra) | ||
120 | + break | ||
121 | + | ||
122 | + if self.has_rule is False: | ||
123 | + print 'NÃO ACHOU REGRA - ' + it.get_word().encode('utf-8') | ||
127 | self.lista_corrigida.append(it.get_token()) #se nao achou regra, entao adiciona a tupla original | 124 | self.lista_corrigida.append(it.get_token()) #se nao achou regra, entao adiciona a tupla original |
128 | if sint: | 125 | if sint: |
129 | - return self.lista_corrigida | 126 | + return self.lista_corrigida |
130 | return filter(None, self.lista_corrigida) | 127 | return filter(None, self.lista_corrigida) |
131 | 128 | ||
132 | 129 | ||
@@ -135,159 +132,185 @@ class AplicaRegras(object): | @@ -135,159 +132,185 @@ class AplicaRegras(object): | ||
135 | self.adaptar_regras_morfo_arvore(lista, p_arvore) | 132 | self.adaptar_regras_morfo_arvore(lista, p_arvore) |
136 | for morpho in self.__root.findall('syntactic'): | 133 | for morpho in self.__root.findall('syntactic'): |
137 | for rule in morpho.findall('rule'): # procura a tag rule | 134 | for rule in morpho.findall('rule'): # procura a tag rule |
138 | - nome_regra = self.corrigir_anotacao(rule.get('name')) | 135 | + nome_regra = self.corrigir_nome_regra(rule.get('name')) |
139 | regra = self.separar_regra(nome_regra) | 136 | regra = self.separar_regra(nome_regra) |
140 | node_pai = tgrep_nodes(p_arvore, regra[0], search_leaves=False) | 137 | node_pai = tgrep_nodes(p_arvore, regra[0], search_leaves=False) |
141 | - if node_pai: | ||
142 | - node_regra = tgrep_nodes(node_pai[0], regra[1].replace('$', '>'), search_leaves=False) | 138 | + if node_pai and rule.find('active').text == "true": |
139 | + node_pai = node_pai[0] | ||
140 | + node_regra = tgrep_nodes(node_pai, regra[1].replace('$', '..'), search_leaves=False) | ||
143 | if node_regra: | 141 | if node_regra: |
144 | - node_esq = tgrep_nodes(node_pai[0], regra[1], search_leaves=False) | ||
145 | - node_esq_pos = tgrep_positions(node_pai[0], regra[1], search_leaves=False) | ||
146 | - node_dir = tgrep_nodes(node_pai[0], regra[2], search_leaves=False) | ||
147 | - node_dir_pos = tgrep_positions(node_pai[0], regra[2], search_leaves=False) | ||
148 | - if node_esq and node_dir: | ||
149 | - print "REGRA SINTÁTICA: " + rule.get('name') | ||
150 | - subnodes = node_esq + node_dir | ||
151 | - for subnode in subnodes: | ||
152 | - self.has_rule = True | ||
153 | - self.alteracoes_nao_implementadas = [None,None] | ||
154 | - self.count_iteracao_regra = -1 | ||
155 | - self.specific = None | ||
156 | - | ||
157 | - for classe in rule.findall('class'): | ||
158 | - self.specific = classe.find('specific') | ||
159 | - if self.specific is not None: | ||
160 | - self.specific = self.__especificos[self.specific.text](subnode.leaves()[0]) | ||
161 | - if self.specific is False: | ||
162 | - self.has_rule = False | ||
163 | - break | ||
164 | - | ||
165 | - # modelo: [['node_esq', ['token', 'ticket']],['node_dir', ['token', 'ticket']]] | ||
166 | - for classe in rule.iter('class'): | ||
167 | - title = classe.find('title') | ||
168 | - if subnode.label() == title.text: | ||
169 | - newpos = classe.find('newpos') | ||
170 | - newprop = classe.find('newprop') | ||
171 | - newtoken = classe.find('newtoken') | ||
172 | - newtokenpos = classe.find('newtokenpos') | ||
173 | - | ||
174 | - | ||
175 | - self.count_iteracao_regra += 1 | ||
176 | - | ||
177 | - if self.specific is not None: | ||
178 | - self.specific = self.__especificos[self.specific.text](subnode.leaves()[0]) | ||
179 | - if self.specific is False: | ||
180 | - self.has_rule = False | ||
181 | - break | ||
182 | - | ||
183 | - if newprop is not None and newtoken is not None: | ||
184 | - if newtokenpos is not None and newtokenpos.text == "0": | ||
185 | - self.alteracoes_nao_implementadas[self.count_iteracao_regra].append([newtoken.text + "_" + self.specific, newprop.text]) | ||
186 | - else: | ||
187 | - self.alteracoes_nao_implementadas[self.count_iteracao_regra].append([self.specific + "_" + newtoken.text, newprop.text]) | ||
188 | - continue | ||
189 | - | ||
190 | - elif newprop is not None: | ||
191 | - self.alteracoes_nao_implementadas[self.count_iteracao_regra].append([self.specific,newprop.text]) | ||
192 | - | ||
193 | - if newtoken is not None and newpos is not None: | ||
194 | - if newtokenpos is not None: | ||
195 | - lista_merge = count * [None] | ||
196 | - lista_merge[int(newpos.text)] = subnode.leaves()[0] | ||
197 | - lista_merge[int(newtokenpos.text)] = newtoken.text | ||
198 | - merge_tokens = "_".join(lista_merge) | ||
199 | - self.alteracoes_nao_implementadas[self.count_iteracao_regra].append([merge_tokens, title.text]) | ||
200 | - else: | ||
201 | - self.alteracoes_nao_implementadas[self.count_iteracao_regra].append([subnode.leaves()[0] + "_" + newtoken.text, title.text]) | 142 | + node_esq_pos = tgrep_positions(node_pai, regra[1], search_leaves=False) |
143 | + node_dir_pos = tgrep_positions(node_pai, regra[2], search_leaves=False) | ||
144 | + if node_esq_pos and node_dir_pos: | ||
145 | + print "REGRA SINTÁTICA ENCONTRADA: " + rule.get('name') | ||
146 | + nodes_positions = node_esq_pos + node_dir_pos | ||
147 | + self.count = -1 | ||
148 | + self.has_rule = True | ||
149 | + | ||
150 | + count_temp = -1 | ||
151 | + for classe in rule.findall('class'): | ||
152 | + count_temp += 1 | ||
153 | + leaves = node_pai[nodes_positions[count_temp]].leaves() | ||
154 | + token = filter(None, leaves)[0] | ||
155 | + specific = classe.find('specific') | ||
156 | + if specific is not None: | ||
157 | + result_specific = self.__especificos[specific.text](token) | ||
158 | + if result_specific is False: | ||
159 | + self.has_rule = False | ||
160 | + | ||
161 | + if self.has_rule is False: | ||
162 | + print "REGRA SINTÁTICA " + rule.get('name') + " INVÁLIDA. PROCURANDO OUTRA..." | ||
163 | + break | ||
202 | 164 | ||
203 | - elif newpos is not None: | ||
204 | - if newpos.text == "-1": | ||
205 | - alteracoes_nao_implementadas[self.count_iteracao_regra].append(None) | ||
206 | - continue | ||
207 | - else: | ||
208 | - #TODO | ||
209 | - if int(newpos.text) == 0: | ||
210 | - self.alteracoes_nao_implementadas[int(newpos.text)] = subnode | ||
211 | - | ||
212 | - elif newtoken is not None: | ||
213 | - token_anterior = self.lista_iteracao_regra[self.count_iteracao_regra][0] | ||
214 | - ticket_anterior = self.lista_iteracao_regra[self.count_iteracao_regra][1] | ||
215 | - if newtokenpos is not None and newtokenpos.text == "0": | ||
216 | - self.lista_iteracao_regra[self.count_iteracao_regra] = [newtoken.text + " " + token_anterior, ticket_anterior] | 165 | + nodes_deleted = [] |
166 | + | ||
167 | + for classe in rule.iter('class'): | ||
168 | + action = classe.find('action') | ||
169 | + newprop = classe.find('newprop') | ||
170 | + | ||
171 | + self.count += 1 | ||
172 | + | ||
173 | + if action is not None: | ||
174 | + action_text = action.text | ||
175 | + | ||
176 | + if action_text == "remove": | ||
177 | + pos_del = nodes_positions[self.count] | ||
178 | + nodes_deleted.append(node_pai[pos_del]) | ||
179 | + node_pai[pos_del] = None | ||
180 | + continue | ||
181 | + | ||
182 | + elif action_text == "invert": | ||
183 | + aux1 = node_pai[nodes_positions[self.count]] | ||
184 | + aux2 = node_pai[nodes_positions[self.count+1]] | ||
185 | + node_pai[nodes_positions[self.count]] = None | ||
186 | + node_pai[nodes_positions[self.count+1]] = None | ||
187 | + node_pai[nodes_positions[self.count]] = aux2 | ||
188 | + node_pai[nodes_positions[self.count+1]] = aux1 | ||
189 | + | ||
190 | + ''' | ||
191 | + elif self.__acoes.has_key(action_text): | ||
192 | + leaves = node_pai[nodes_positions[self.count]].leaves() | ||
193 | + token = filter(None, leaves)[0] | ||
194 | + result_action = self.__acoes[action_text](token) | ||
195 | + | ||
196 | + #self.lista_iteracao_regra.append([result_action, tupla[1]]) | ||
197 | + nodes_positions[self.count] = 'TODO' | ||
198 | + | ||
199 | + if action_text == "concate_intens": | ||
200 | + leaves_prev = node_pai[nodes_positions[self.count-1]].leaves() | ||
201 | + token_prev = filter(None, leaves_prev)[0] | ||
202 | + title_text = classe.find('title').text | ||
203 | + if title_text == "ADV-R": | ||
204 | + node_prev = nodes_deleted.pop() | ||
205 | + label_prev = node_prev[0][0].label() | ||
206 | + token_prev = filter(None, node_pai[nodes_positions[count_temp-1]].leaves())[0] | ||
207 | + token = filter(None, node_pai[nodes_positions[count_temp]].leaves())[0] | ||
208 | + token_concate = token_prev + "_" + token | ||
209 | + node_pai[nodes_positions[count_temp-1]][0][0][0] = token_concate | ||
210 | + newprop = "" | ||
211 | + if label_prev[:-2] == "VB": | ||
212 | + newprop = "VBi" | ||
213 | + elif label_prev[:-3] == "ADJ": | ||
214 | + newprop = "ADJi" | ||
215 | + | ||
216 | + # TODO: Verifica qual newprop adicionada e remove o nó corrente | ||
217 | + node_pai[nodes_positions[count_temp-1]][0][0].set_label(newprop) | ||
218 | + pos_del = nodes_positions[self.count] | ||
219 | + node_pai[pos_del] = None | ||
220 | + | ||
217 | else: | 221 | else: |
218 | - self.lista_iteracao_regra[self.count_iteracao_regra] = [token_anterior + " " + newtoken.text, ticket_anterior] | 222 | + token_prev = filter(None, nodes_deleted.pop().leaves())[0] |
223 | + token = filter(None, node_pai[nodes_positions[count_temp]].leaves())[0] | ||
224 | + token_concate = token + "_" + token_prev | ||
225 | + node_pai[nodes_positions[count_temp]][0][0][0] = token_concate | ||
219 | 226 | ||
220 | - if self.has_rule: | ||
221 | - print self.alteracoes_nao_implementadas[0] | ||
222 | - self.lista_corrigida.append(filter(None, self.lista_iteracao_regra)[0]) | ||
223 | - break | 227 | + elif action_text == "concate_neg": |
228 | + print "TODO" | ||
229 | + ''' | ||
224 | 230 | ||
231 | + if newprop is not None: | ||
232 | + node_pai[nodes_positions[self.count]].set_label(newprop.text) | ||
233 | + | ||
234 | + break | ||
235 | + | ||
225 | return self.converter_arv_para_lista(p_arvore) | 236 | return self.converter_arv_para_lista(p_arvore) |
237 | + | ||
226 | 238 | ||
239 | + # Aplica regras morfológicas na árvore sintática | ||
227 | def adaptar_regras_morfo_arvore(self, lista, arvore): | 240 | def adaptar_regras_morfo_arvore(self, lista, arvore): |
228 | lista_pos_arv = [] | 241 | lista_pos_arv = [] |
242 | + # Pega as posições das classificações morfológicas dos tokens na arvore sintática | ||
229 | for tupla in lista: | 243 | for tupla in lista: |
230 | - string_grep = self.corrigir_anotacao(tupla[1]) + " < " + tupla[0].lower() | 244 | + string_grep = self.corrigir_nome_regra(tupla[1]) + " < " + tupla[0].lower() |
231 | node = tgrep_positions(arvore, string_grep) | 245 | node = tgrep_positions(arvore, string_grep) |
246 | + if not node: | ||
247 | + string_grep = self.corrigir_nome_regra(tupla[1]) + " < " + self.remover_acento(tupla[0].lower()) | ||
248 | + node = tgrep_positions(arvore, string_grep) | ||
232 | if node[0] in lista_pos_arv: | 249 | if node[0] in lista_pos_arv: |
233 | node.reverse() | 250 | node.reverse() |
234 | lista_pos_arv.append(node[0]) | 251 | lista_pos_arv.append(node[0]) |
252 | + | ||
253 | + # Aplica regras morfológicas na lista | ||
235 | morfo = self.aplicar_regras_morfo(lista, sint=True) | 254 | morfo = self.aplicar_regras_morfo(lista, sint=True) |
255 | + | ||
256 | + # Corrige arvore de acordo com a lista após aplicar as regras morfológicas | ||
236 | for i in range(0, len(morfo)): | 257 | for i in range(0, len(morfo)): |
258 | + if morfo[i] is not None and morfo[i][1] == "NTK": | ||
259 | + new_node = self.gerar_no(morfo[i]) | ||
260 | + arvore[lista_pos_arv[i-1][:-2]].insert(2, new_node) | ||
261 | + try: | ||
262 | + lista_pos_arv.insert(i,lista_pos_arv[i]) | ||
263 | + except: | ||
264 | + continue | ||
265 | + | ||
237 | arv_ticket = arvore[lista_pos_arv[i]].label() | 266 | arv_ticket = arvore[lista_pos_arv[i]].label() |
238 | arv_token = arvore[lista_pos_arv[i]][0] | 267 | arv_token = arvore[lista_pos_arv[i]][0] |
268 | + | ||
239 | if morfo[i] is None: | 269 | if morfo[i] is None: |
240 | - arvore[lista_pos_arv[i][:-1]] = None | 270 | + arvore[lista_pos_arv[i]] = None |
271 | + | ||
241 | elif arv_token != morfo[i][0] and arv_ticket != morfo[i][1]: | 272 | elif arv_token != morfo[i][0] and arv_ticket != morfo[i][1]: |
242 | arvore[lista_pos_arv[i]][0] = morfo[i][0] | 273 | arvore[lista_pos_arv[i]][0] = morfo[i][0] |
243 | - arvore[lista_pos_arv[i]].set_label(self.corrigir_anotacao(morfo[i][1])) | 274 | + arvore[lista_pos_arv[i]].set_label(morfo[i][1]) |
275 | + | ||
244 | elif arv_token != morfo[i][0]: | 276 | elif arv_token != morfo[i][0]: |
245 | arvore[lista_pos_arv[i]][0] = morfo[i][0] | 277 | arvore[lista_pos_arv[i]][0] = morfo[i][0] |
278 | + | ||
246 | elif arv_ticket != morfo[i][1]: | 279 | elif arv_ticket != morfo[i][1]: |
247 | - arvore[lista_pos_arv[i]].set_label(self.corrigir_anotacao(morfo[i][1])) | ||
248 | - else: | ||
249 | - continue | ||
250 | - | ||
251 | - nodes_none = tgrep_positions(arvore, 'None') | ||
252 | - for node in nodes_none: | ||
253 | - arvore[node[:-1]].remove(None) | 280 | + arvore[lista_pos_arv[i]].set_label(morfo[i][1]) |
254 | 281 | ||
282 | + # Converte árvore sintática para uma lista de tuplas (igual a lista morfológica) | ||
255 | def converter_arv_para_lista(self, arvore): | 283 | def converter_arv_para_lista(self, arvore): |
256 | - folhas = arvore.leaves() | 284 | + folhas = filter(None, arvore.leaves()) |
257 | lista_nodes = [] | 285 | lista_nodes = [] |
258 | for folha in folhas: | 286 | for folha in folhas: |
259 | pos = tgrep_positions(arvore, folha) | 287 | pos = tgrep_positions(arvore, folha) |
260 | node = arvore[pos[0][:-1]] | 288 | node = arvore[pos[0][:-1]] |
261 | #decode node[0] | 289 | #decode node[0] |
262 | - lista_nodes.append([node[0], self.corrigir_anotacao(node.label())]) | 290 | + lista_nodes.append([node[0], self.corrigir_nome_regra(node.label())]) |
263 | return lista_nodes | 291 | return lista_nodes |
264 | 292 | ||
293 | + def remover_acento(self, texto): | ||
294 | + return normalize('NFKD', texto.encode('utf-8').decode('utf-8')).encode('ascii', 'ignore') | ||
265 | 295 | ||
266 | - def criar_ptree(self, s): | 296 | + # Gera um ParentedTree do NLTK apartir da string recebida |
297 | + def gerar_no(self, s): | ||
267 | all_ptrees = [] | 298 | all_ptrees = [] |
268 | - ptree = ParentedTree.convert(Tree.fromstring(s)) | 299 | + t_string = '('+s[1] + ' ' + s[0]+')' |
300 | + ptree = ParentedTree.convert(Tree.fromstring(t_string)) | ||
269 | all_ptrees.extend(t for t in ptree.subtrees() | 301 | all_ptrees.extend(t for t in ptree.subtrees() |
270 | if isinstance(t, Tree)) | 302 | if isinstance(t, Tree)) |
271 | return ptree | 303 | return ptree |
272 | 304 | ||
273 | - def separar_new_tokens(self, lista): | ||
274 | - for index, tupla in enumerate(lista): | ||
275 | - if '_' in tupla[0]: | ||
276 | - if 'VB' in tupla[1]: | ||
277 | - token_split = tupla[0].split('_') | ||
278 | - tupla[0] = token_split[0] | ||
279 | - lista.append([token_split[1],'NTK']) | ||
280 | - else: | ||
281 | - token_split = tupla[0].split('_') | ||
282 | - tupla[0] = token_split[0] | ||
283 | - lista.insert(index+1, [token_split[1],'NTK']) | ||
284 | - | ||
285 | - def corrigir_anotacao(self, anotacao): | 305 | + # Corrige nome da regra descrita no arquivo de regras para como está na árvore sintática |
306 | + def corrigir_nome_regra(self, anotacao): | ||
286 | split = anotacao.split('_') | 307 | split = anotacao.split('_') |
287 | for i in range(0, len(split)): | 308 | for i in range(0, len(split)): |
288 | - split[i] = split[i].replace('-','_') | 309 | + split[i] = re.sub(r"[-+]","_", split[i]) |
310 | + split[i] = re.sub(r"\$","_S",split[i]) | ||
289 | return "-".join(split).encode('utf-8') | 311 | return "-".join(split).encode('utf-8') |
290 | 312 | ||
313 | + # Separa a regra por nó pai e seus filhos | ||
291 | def separar_regra(self, regra): | 314 | def separar_regra(self, regra): |
292 | split = regra.split("(") | 315 | split = regra.split("(") |
293 | split[1] = split[1].replace(")","").split("-") | 316 | split[1] = split[1].replace(")","").split("-") |
@@ -298,22 +321,24 @@ class AplicaRegras(object): | @@ -298,22 +321,24 @@ class AplicaRegras(object): | ||
298 | split[2] = ' $ '.join(split[2]) | 321 | split[2] = ' $ '.join(split[2]) |
299 | return split | 322 | return split |
300 | 323 | ||
324 | + # Gera nome de regra apartir de uma lista | ||
301 | def gerar_nome_regra(self, lista): | 325 | def gerar_nome_regra(self, lista): |
302 | - self.__nomeRegra = [] | 326 | + nome_regra = [] |
303 | for t in lista: | 327 | for t in lista: |
304 | - self.__nomeRegra.append(t[1]) | ||
305 | - return "_".join(self.__nomeRegra) | 328 | + nome_regra.append(t[1]) |
329 | + return "_".join(nome_regra) | ||
306 | 330 | ||
307 | def verificar_adv_tempo(self, token): | 331 | def verificar_adv_tempo(self, token): |
308 | for tupla in self.lista: | 332 | for tupla in self.lista: |
309 | if self.dicionarios.has_adverbio_tempo(tupla[0]): | 333 | if self.dicionarios.has_adverbio_tempo(tupla[0]): |
310 | - return self.verificar_vb_infinitivo(token) | 334 | + return True |
311 | return False | 335 | return False |
312 | 336 | ||
337 | + def verificar_excecao_plural(self, token): | ||
338 | + return self.dicionarios.has_excecao_plural(token) | ||
339 | + | ||
313 | def verificar_vb_infinitivo(self, token): | 340 | def verificar_vb_infinitivo(self, token): |
314 | - if self.dicionarios.has_verbo_infinitivo(token): | ||
315 | - return self.dicionarios.get_verbo_infinitivo(token) | ||
316 | - return False | 341 | + return self.dicionarios.has_verbo_infinitivo(token) |
317 | 342 | ||
318 | def verificar_preposicao(self, token): | 343 | def verificar_preposicao(self, token): |
319 | return self.dicionarios.has_preposicao(token) | 344 | return self.dicionarios.has_preposicao(token) |
@@ -331,29 +356,38 @@ class AplicaRegras(object): | @@ -331,29 +356,38 @@ class AplicaRegras(object): | ||
331 | return self.dicionarios.has_adverbio_intensidade(token) | 356 | return self.dicionarios.has_adverbio_intensidade(token) |
332 | 357 | ||
333 | def verificar_vb_muda_negacao(self, token): | 358 | def verificar_vb_muda_negacao(self, token): |
334 | - if self.dicionarios.has_verbo_muda_negacao(token): | ||
335 | - return self.dicionarios.get_verbo_muda_negacao(token) | ||
336 | - return False | 359 | + return self.dicionarios.has_verbo_muda_negacao(token) |
360 | + | ||
361 | + def get_vb_infinitivo(self, token): | ||
362 | + if self.dicionarios.has_verbo_infinitivo(token): | ||
363 | + return self.dicionarios.get_verbo_infinitivo(token) | ||
364 | + return token | ||
365 | + | ||
366 | + def get_token_intensidade(self, token): | ||
367 | + print 'TODO' | ||
368 | + | ||
337 | 369 | ||
370 | + # Simplifica a sentença para que possa evitar a ditalogia | ||
338 | def simplificar_sentenca(self, lista): | 371 | def simplificar_sentenca(self, lista): |
372 | + lista_simplificada = list(lista) | ||
339 | it = Iterator() | 373 | it = Iterator() |
340 | - it.load(lista) | 374 | + it.load(lista_simplificada) |
341 | num = False | 375 | num = False |
342 | - nova_lista = [] | ||
343 | while(it.has_next()): | 376 | while(it.has_next()): |
344 | - token = it.get_word() | ||
345 | tag = it.get_ticket() | 377 | tag = it.get_ticket() |
346 | 378 | ||
347 | if tag == "NUM": | 379 | if tag == "NUM": |
348 | num = True | 380 | num = True |
349 | 381 | ||
350 | - if tag[-2:] == "-P": | ||
351 | - singular = self.analisar_plural(token) | ||
352 | - lista[it.get_count()][0] = singular | 382 | + if tag[-2:] == "-P" and self.verificar_excecao_plural(it.get_word()): |
383 | + singular = self.analisar_plural(it.get_word()) | ||
384 | + lista_simplificada[it.get_count()][0] = singular | ||
353 | 385 | ||
354 | - if num: return self.converter_extenso(nova_lista) | ||
355 | - return nova_lista | 386 | + if num: |
387 | + return self.converter_extenso(lista_simplificada) | ||
388 | + return lista_simplificada | ||
356 | 389 | ||
390 | + # Alterar uma palavra do plural para o singular | ||
357 | def analisar_plural(self, token): | 391 | def analisar_plural(self, token): |
358 | if(token[-3:] == "OES" or token[-2:] == "AES" or token[-2:] == "AOS"): | 392 | if(token[-3:] == "OES" or token[-2:] == "AES" or token[-2:] == "AOS"): |
359 | return token[0:-3]+"AO" | 393 | return token[0:-3]+"AO" |
@@ -376,32 +410,37 @@ class AplicaRegras(object): | @@ -376,32 +410,37 @@ class AplicaRegras(object): | ||
376 | else: | 410 | else: |
377 | return token | 411 | return token |
378 | 412 | ||
413 | + # Converter número por extenso para numeral | ||
379 | def converter_extenso(self, lista): | 414 | def converter_extenso(self, lista): |
380 | - lista_aux = [] | ||
381 | - index_deleted = [] | 415 | + lista_extensos = [] |
416 | + indices_deletar = [] | ||
382 | count = 0 | 417 | count = 0 |
383 | - is_running = False | 418 | + is_sequence = False |
384 | 419 | ||
385 | for i in range(0, len(lista)): | 420 | for i in range(0, len(lista)): |
386 | token = lista[i][0] | 421 | token = lista[i][0] |
387 | tag = lista[i][1] | 422 | tag = lista[i][1] |
388 | if tag == "NUM": | 423 | if tag == "NUM": |
389 | - if (is_running is False and len(lista_aux) == count): | ||
390 | - lista_aux.append([i,[token]]) | ||
391 | - is_running = True | 424 | + # Verifico se não há sequência de obtenção de extenso em andamento para começar a obter um nova sequência |
425 | + if (is_sequence is False): # and len(lista_extensos) == count (???) | ||
426 | + lista_extensos.append([i,[token]]) # i = Posição do primeiro extenso encontrado, token = número por extenso | ||
427 | + is_sequence = True | ||
392 | else: | 428 | else: |
393 | - lista_aux[count][1].append(token) | ||
394 | - index_deleted.append(i) | ||
395 | - elif (is_running): | 429 | + lista_extensos[count][1].append(token) # Pego número por extenso que está na sequência e adiciona na lista |
430 | + indices_deletar.append(i) # Insiro indice na lista para ser removido depois | ||
431 | + elif (is_sequence): | ||
432 | + # 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 | ||
396 | if ((lista[i-1][1] == "NUM") and (lista[i+1][1] == "NUM") and (tag == "CONJ")): | 433 | if ((lista[i-1][1] == "NUM") and (lista[i+1][1] == "NUM") and (tag == "CONJ")): |
397 | - index_deleted.append(i) | 434 | + indices_deletar.append(i) |
398 | else: | 435 | else: |
399 | - is_running = False | 436 | + # A sequência foi quebrada, o que significa que selecionamos o extenso do número por completo |
437 | + # Podemos agora procurar por outra sequencia de número por extenso na lista | ||
438 | + is_sequence = False | ||
400 | count += 1 | 439 | count += 1 |
401 | 440 | ||
402 | - for i in lista_aux: | ||
403 | - ext = extenso(' '.join(i[1])) | ||
404 | - lista[i[0]] = [ext, "NUM"] | 441 | + for extenso in lista_extensos: |
442 | + ext = convert_extenso(' '.join(extenso[1])) | ||
443 | + lista[extenso[0]] = [ext, "NUM"] | ||
405 | 444 | ||
406 | - deque((list.pop(lista, i) for i in sorted(index_deleted, reverse=True)), maxlen=0) | 445 | + deque((list.pop(lista, i) for i in sorted(indices_deletar, reverse=True)), maxlen=0) |
407 | return lista | 446 | return lista |
408 | \ No newline at end of file | 447 | \ No newline at end of file |