def verificar_fatoravel(self, gramatica, n): if gramatica.existe_recursao_esq(): raise OperacaoError(" a gramática possui derivações à esquerda") if n > 0: return gramatica.eh_fatoravel_em_n_passos(n) else: raise OperacaoError(" n deve ser um inteiro maior que zero")
def remover_simples(self, gramatica): if not gramatica.existe_producoes_simples(): raise OperacaoError(" a gramática não possui produções simples") elif not gramatica.eh_epsilon_livre(): raise OperacaoError(" a gramática deve ser epsilon-livre") else: nova_gramatica, na = gramatica.remove_simples() return nova_gramatica, na
def remove_recursao_esq(self): if self.existe_recursao_esq(): raise OperacaoError(" a gramática não possui recursão à esquerda") elif not self.eh_propria(): raise OperacaoError(" a gramática não é própria") else: print() pass
def transformar_em_propria(self, gramatica): if gramatica.eh_propria(): raise OperacaoError(" a gramática já é própria") else: resultantes = [] conjuntos = [] try: epsilon_livre, ne = self.transformar_epsilon_livre(gramatica) resultantes.append(epsilon_livre) conjuntos.append(ne) except OperacaoError as e: epsilon_livre = gramatica conjuntos.append(epsilon_livre.obtem_ne()) try: sem_simples, na = self.remover_simples(epsilon_livre) resultantes.append(sem_simples) conjuntos.append(na) except OperacaoError as e: sem_simples = epsilon_livre conjuntos.append(sem_simples.obtem_na()) try: sem_inuteis, nf_vi = self.remover_inuteis(sem_simples) resultantes.extend(sem_inuteis) conjuntos.extend(nf_vi) except OperacaoError as e: sem_inuteis = [sem_simples] conjuntos.extend([sem_simples.obtem_nf(), sem_simples.obtem_vi()]) propria = sem_inuteis[-1] propria.set_nome(gramatica.get_nome() + " (própria)") return resultantes, conjuntos
def remover_inuteis(self, gramatica): if not gramatica.existem_inuteis(): raise OperacaoError(" a gramática não possui produções inúteis") else: resultantes = [] conjuntos = [] try: sem_infertil, nf = self.remover_inferteis(gramatica) resultantes.append(sem_infertil) conjuntos.append(nf) except OperacaoError as e: sem_infertil = gramatica conjuntos.append(sem_infertil.obtem_nf()) try: sem_inalcancavel, vi = self.remover_inalcancaveis(sem_infertil) conjuntos.append(vi) except OperacaoError as e: sem_inalcancavel = sem_infertil conjuntos.append(sem_inalcancavel.obtem_vi()) sem_inalcancavel.set_nome(gramatica.get_nome() + " (sem inúteis)") resultantes.append(sem_inalcancavel) return resultantes, conjuntos
def remove_inferteis(self): if not self.existe_inferteis(): raise OperacaoError(" a gramática não possui nenhuma produção infértil") else: sem_inferteis = GLCEditavel(self) nf = self.obtem_nf() # Símbolos férteis if self._vn_inicial not in nf: raise OperacaoError(" a gramática representa uma linguagem vazia") inferteis = self._nao_terminais.difference(nf) for simbolo in inferteis: sem_inferteis.remove_vn(simbolo) glc = sem_inferteis.obter_glc_padrao(self.get_nome() + " (sem inférteis)") return glc, inferteis
def remove_simples(self): if not self.existe_producoes_simples(): raise OperacaoError(" a gramática não possui nenhuma produção simples") else: na = self.obtem_na() sem_simples = GLCEditavel(self) # Remove produções simples for A in sem_simples._conjunto_producoes: producoes = list(sem_simples._conjunto_producoes[A]) for derivacao in producoes: if derivacao.eh_simples(): sem_simples.remove_producao(A, derivacao) # Adiciona produções for A in sem_simples._conjunto_producoes: for B in set(na[A]) - set([A]): for prod in sem_simples._conjunto_producoes[B]: sem_simples.adiciona_producao(A, Producao(A, list(prod.get_derivacao()))) # Atualiza produções houve_mudança = True while houve_mudança: houve_mudança = False for A in sem_simples._conjunto_producoes: for B in set(na[A]) - set([A]): diff = set(sem_simples._conjunto_producoes[B]) - set(sem_simples._conjunto_producoes[A]) if len(diff) > 0: for prod in diff: sem_simples.adiciona_producao(A, Producao(A, list(prod.get_derivacao()))) houve_mudança = True glc = sem_simples.obter_glc_padrao(self.get_nome() + " (sem prod. simples)") return glc, na
def transforma_epsilon_livre(self): if self.eh_epsilon_livre(): raise OperacaoError(" a gramática já é epsilon-livre") else: sem_epsilon = GLCEditavel(self) ne = self.obtem_ne() # Símbolos que derivam & for A in self._nao_terminais: producoes = self._conjunto_producoes[A] for x in producoes: indices = [] prod = x.get_derivacao() if prod.eh_epsilon(): sem_epsilon.remove_producao(A, x) else: for y in prod: if y in ne: indices.append(prod.index(y)) if len(prod) > 1 and len(indices) > 0: powerset = list(self.__powerset(indices)) powerset.pop(0) # Remove conjunto vazio for item in powerset: nova_prod = list(prod) index = ''.join(str(s) for s in list(item)) index = int(index) nova_prod.pop(index) sem_epsilon.adiciona_producao(A, Producao(A, nova_prod)) if self._vn_inicial in ne: prod = Producao(self._vn_inicial, [Vt(epsilon)]) sem_epsilon.adiciona_producao(self._vn_inicial, prod) glc = sem_epsilon.obter_glc_padrao(self.get_nome() + " (& livre)") return glc, ne
def remove_inalcancaveis(self): if not self.existe_inalcancavel(): raise OperacaoError(" a gramática não possui nenhuma produção inalcançável") else: sem_inalc = GLCEditavel(self) vi = self.obtem_vi() # Símbolos alcançáveis inalcancaveis = self._nao_terminais.difference(vi) for simbolo in inalcancaveis: sem_inalc.remove_vn(simbolo) glc = sem_inalc.obter_glc_padrao(self.get_nome() + " (sem inalcançáveis)") return glc, inalcancaveis
def remover_recursao(self, gramatica): if not gramatica.existe_recursao_esq(): raise OperacaoError(" a gramática não possui nenhuma recursão à esquerda") else: resultantes = [] try: propria, conjuntos = self.transformar_em_propria(gramatica) resultantes.extend(propria) except OperacaoError as e: propria = [gramatica] sem_recursao, recursoes = propria[-1].remove_recursao_esq() resultantes.append(sem_recursao) return resultantes, recursoes
def remover_inalcancaveis(self, gramatica): if not gramatica.existe_inalcancavel(): raise OperacaoError(" a gramática não possui produções inalcançáveis") else: nova_gramatica, vi = gramatica.remove_inalcancaveis() return nova_gramatica, vi
def remover_inferteis(self, gramatica): if not gramatica.existe_inferteis(): raise OperacaoError(" a gramática não possui produções inférteis") else: nova_gramatica, nf = gramatica.remove_inferteis() return nova_gramatica, nf
def transformar_epsilon_livre(self, gramatica): if gramatica.eh_epsilon_livre(): raise OperacaoError(" a gramática já é epsilon-livre") else: nova_gramatica, ne = gramatica.transforma_epsilon_livre() return nova_gramatica, ne
def eh_fatoravel_em_n_passos(self, n): if self.esta_fatorada(): raise OperacaoError(" a gramática já está fatorada") else: i = 0 fatorada = GLCEditavel(self) nao_terminais = [] nao_terminais.extend(self._nao_terminais) while nao_terminais: nt = nao_terminais[0] if not fatorada.__nt_esta_fatorado(fatorada, nt): if i < n: producoes = list(fatorada._conjunto_producoes[nt]) j = 0 firsts = [] while j < len(producoes)-1: k = j + 1 producao = producoes[j] first_prod = fatorada.first_producao(producao) if not(first_prod in firsts): # Se esse first já não foi analizado outras_prod = [] while k < len(producoes): prod = producoes[k] first_outra_prod = fatorada.first_producao(prod) if first_outra_prod not in firsts: intersec = first_prod.intersection(first_outra_prod) if intersec: firsts.extend(intersec) outras_prod.append(prod) k += 1 if outras_prod: todas_producoes = list(set(outras_prod).union(set([producao]))) novas_prod = [] for x in todas_producoes: if len(x.get_derivacao()) > 0: simb = x.get_derivacao()[0] novas_prod.append(x) if not isinstance(simb, Vt): # ND indireto prox_deriv = [] prox_deriv.append(simb) while prox_deriv: outro_simb = prox_deriv[0] derivacao = fatorada._conjunto_producoes[outro_simb] indexes = [] # indices das produções com o nao terminal for y in novas_prod: if y.get_derivacao()[0] == outro_simb: indexes.append(novas_prod.index(y)) for d in derivacao: for index in indexes: di = list(novas_prod[index].get_derivacao()) di.pop(0) if di is None: di = [] nova_deriv = [] if not d.eh_epsilon() or di == list(): nova_deriv = list(d.get_derivacao()) nova_deriv.extend(di) novas_prod.append(Producao(novas_prod[index].get_gerador(), nova_deriv)) if isinstance(nova_deriv[0], Vn): prox_deriv.append(nova_deriv[0]) v = 0 for index in indexes: if index-v < 0: novas_prod.pop(0) else: novas_prod.pop(index-v) v += 1 prox_deriv.remove(outro_simb) # Commom substring a = 0 b = 1 commom_subtrings = set() removidos = set() while a < len(novas_prod): sa = str(novas_prod[a]) b = a + 1 while b < len(novas_prod): if a != b: start = self.__common_start(sa, str(novas_prod[b])) if start != '' and start != ' ': strings = set(commom_subtrings) if strings: for c in strings: com_sub = self.__common_start(c, start) if com_sub != '' and com_sub != ' ': commom_subtrings.add(com_sub) removidos.add(c) else: commom_subtrings.add(start) else: commom_subtrings.add(start) b += 1 a += 1 for r in removidos: commom_subtrings.remove(r) adicionar = list(novas_prod) for common_s in commom_subtrings: # Fatora simbolos = [] common_s = common_s.replace(" ", "") for s in common_s: if s.islower(): simbolos.append(Vt(s)) else: simbolos.append(Vn(s)) novo_nt = fatorada.novo_simbolo(str(nt)[0]) novo_nt = Vn(novo_nt) simbolos.append(novo_nt) nao_terminais.append(novo_nt) fatorada.adiciona_nao_terminal(novo_nt) fatorada.adiciona_producao(nt, Producao(nt, simbolos)) # Produções do novo não terminal fim_commom = len(common_s) for p in novas_prod: if p.get_derivacao()[0] == simbolos[0]: resto_prod = p.get_derivacao()[fim_commom:] if len(resto_prod) == 0: resto_prod = [Vt("&")] fatorada.adiciona_producao(novo_nt, Producao(novo_nt, resto_prod)) adicionar.remove(p) for a in adicionar: fatorada.adiciona_producao(nt, Producao(nt, a.get_derivacao())) # Remover producoes não fatoradas anteriores for p in todas_producoes: fatorada.remove_producao(nt, p) i += 1 # Um passo feito j += 1 else: return False, None nao_terminais.remove(nt) glc = fatorada.obter_glc_padrao(self.get_nome() + "(fatorada)") return True, glc