package Portugol.Language.Criar; import Portugol.Language.Analisador.Expressao; import Portugol.Language.Analisador.Keyword; import Portugol.Language.Analisador.Operador; import Portugol.Language.Analisador.ParteDeExpresion; import Portugol.Language.Analisador.Simbolo; import Portugol.Language.Analisador.TipoClasse; import Portugol.Language.Analisador.TipoRegisto; import Portugol.Language.Analisador.Variavel; import Portugol.Language.Utilitario.IteratorCodeParams; import Portugol.Language.Utilitario.IteratorExpression; import Portugol.Language.Utilitario.LanguageException; import Portugol.Language.Utilitario.Values; //import Portugol.Language.Criar.Subrutine; import java.util.Stack; import java.util.Vector; public class ExpandFluxogram { public static String VERSION = "Versão:2.0 \t(c)Augusto Bilabila e David Silva Barrera"; public static void ExpandSubrutine(BloqueSubrutine rutina) throws LanguageException { NodeInstruction pt = rutina.getStartNode(); Vector memory = new Vector();//rutina.memory; Stack stack = new Stack(); while (pt != null) { //fazer as variaveis if (pt.GetType() == Keyword.DEFINIR) { //si existe una variable de registro en definicion entonces todas las variables //van como campos de este pt = ExpandDefinirSimbol.ExpandVariable(pt, stack.size(), memory); } else if (pt.GetType() == Keyword.CALCULAR) { VerifyCalculate(pt, memory); } //fazer a leitura das variaveis else if (pt.GetType() == Keyword.RETORNE) { VerifyRetorno(pt, memory); } //fazer a leitura das variaveis else if (pt.GetType() == Keyword.LEIA) { pt = ExpandLer.ExpandRead(pt, stack.size(), memory); } //verificar a escrita else if (pt.GetType() == Keyword.ESCREVA) { VerifyWRITE(pt, memory); } // nos dos blocos vao para a pilha else if (pt.GetType() == Keyword.SE || pt.GetType() == Keyword.PARA || pt.GetType() == Keyword.ENQUANTO || pt.GetType() == Keyword.FAZ || pt.GetType() == Keyword.ESCOLHA || pt.GetType() == Keyword.REPETE) { stack.push(pt); } //limpar variaveis detro do escolhe // o senao esta ao mesmo nivel das variaveis else if (pt.GetType() == Keyword.SENAO) { if (stack.isEmpty()) { throw new LanguageException( pt.GetCharNum(), pt.GetText(), "O < SENAO > NÃO PODE EXISTIR SEM O < SE > ", "POR FAVOR COLOQUE O < SE > ANTES DO < SENAO >"); } // obter o IF da pilha NodeInstruction n = (NodeInstruction) stack.peek(); //ERRO if (n.GetType() != Keyword.SE) { throw new LanguageException( pt.GetCharNum(), pt.GetText(), "A ESTRUTURA :\"" + n.GetText() + "\" ESTÁ ABERTA", " ESCREVA A INSTRUÇÃO FIM" + n.GetTextKey() + " E NÃO \"" + pt.GetText() + "\""); } cleanMemory(stack.size(), memory); } else if (pt.GetType() == Keyword.CASO || pt.GetType() == Keyword.DEFEITO) { cleanMemory(stack.size(), memory); } // --------------------- Fazer os IFS ---------------------------- else if (pt.GetType() == Keyword.FIMSE) { if (stack.isEmpty()) { throw new LanguageException( pt.GetCharNum(), pt.GetText(), "O < FIMSE > NÃO PODE EXISTIR SEM O < SE > ", "POR FAVOR COLOQUE O < SE > ANTES DO < FIMSE >"); } // obter o IF da pilha NodeInstruction n = (NodeInstruction) stack.pop(); //ERRO if (n.GetType() != Keyword.SE) { throw new LanguageException( pt.GetCharNum(), pt.GetText(), "A ESTRUTURA :\"" + n.GetText() + "\" ESTÁ ABERTA", " ESCREVA A INSTRUÇÃO FIM" + n.GetTextKey() + " E NÃO \"" + pt.GetText() + "\""); } cleanMemory(stack.size() + 1, memory); ExpandSe.ExpandIF(n, stack.size(), memory); } // --------------------- Fazer os WHILE ---------------------------- else if (pt.GetType() == Keyword.FIMENQUANTO) { if (stack.isEmpty()) { throw new LanguageException( pt.GetCharNum(), pt.GetText(), "O < FIMENQUANTO > NÃO PODE EXISTIR SEM O < ENQUANTO > ", "POR FAVOR COLOQUE O < ENQUANTO > ANTES DO < FIMENQUANTO >"); } NodeInstruction n = (NodeInstruction) stack.pop(); if (n.GetType() != Keyword.ENQUANTO) { throw new LanguageException( pt.GetCharNum(), pt.GetText(), "O CICLO :\"" + n.GetText() + "\" ESTÁ ABERTO", " ESCREVA A INSTRUÇÃO QUE INDICA O FIM DO CICLO E NÃO \"" + pt.GetText() + "\""); } ExpandEnquanto.ExpandWHILE(n, stack.size(), memory); } //------------------------- fazer os FAZ ENQUANTO------------------------- else if (pt.GetType() == Keyword.FAZENQUANTO) { if (stack.isEmpty()) { throw new LanguageException( pt.GetCharNum(), pt.GetText(), "O < ENQUANTO > NÃO PODE EXISTIR SEM O < FAZ > ", "POR FAVOR COLOQUE O < FAZ > ANTES DO < ENQUANTO >"); } //-------------------- obter o FAZ da pilha -------------- NodeInstruction n = (NodeInstruction) stack.pop(); if (n.GetType() != Keyword.FAZ) { throw new LanguageException( pt.GetCharNum(), pt.GetText(), "O CICLO :\"" + n.GetText() + "\" ESTÁ ABERTO", " ESCREVA A INSTRUÇÃO QUE INDICA O FIM DO CICLO E NÃO \"" + pt.GetText() + "\""); } ExpandFazEnquanto.ExpandDoWhile(n, pt, stack.size(), memory); cleanMemory(stack.size() + 1, memory); } //------------------------- fazer os REPETE ------------------------- else if (pt.GetType() == Keyword.ATE) { if (stack.isEmpty()) { throw new LanguageException( pt.GetCharNum(), pt.GetText(), "O < ATE > NÃO PODE EXISTIR SEM O < REPITA > ", "POR FAVOR COLOQUE O < REPITA > ANTES DO < ATE >"); } //-------------------- obter o Repete da pilha -------------- NodeInstruction n = (NodeInstruction) stack.pop(); if (n.GetType() != Keyword.REPETE) { throw new LanguageException( pt.GetCharNum(), pt.GetText(), "O CICLO :\"" + n.GetText() + "\" ESTÁ ABERTO", " ESCREVA A INSTRUÇÃO QUE INDICA O FIM DO CICLO E NÃO \"" + pt.GetText() + "\""); } ExpandRepeteAte.ExpandRepeat(n, pt, stack.size(), memory); cleanMemory(stack.size() + 1, memory); } //-------------------------- Fazer os FOR ----------------------- else if (pt.GetType() == Keyword.FIMPARA) { if (stack.isEmpty()) { throw new LanguageException( pt.GetCharNum(), pt.GetText(), "O < FIMPARA > NÃO PODE EXISTIR SEM O < PARA > ", "POR FAVOR COLOQUE O < PARA > ANTES DO < FIMPARA >"); } //-------Obter o PARA da pilha --------- NodeInstruction n = (NodeInstruction) stack.pop(); if (n.GetType() != Keyword.PARA) { throw new LanguageException( pt.GetCharNum(), pt.GetText(), "O CICLO :\"" + n.GetText() + "\" ESTÁ ABERTO", " ESCREVA A INSTRUÇÃO QUE INDICA O FIM DO CICLO E NÃO \"" + pt.GetText() + "\""); } ExpandPara.ExpandFOR(n, stack.size(), memory); cleanMemory(stack.size() + 1, memory); } // --------------------- Criar os CASOS ------------------------ else if (pt.GetType() == Keyword.FIMESCOLHE) { if (stack.isEmpty()) { throw new LanguageException( pt.GetCharNum(), pt.GetText(), "O < FIM ESCOLHE > NÃO PODE EXISTIR SEM O < ESCOLHA > ", "POR FAVOR COLOQUE O < ESCOLHA > ANTES DO < FIMESCOLHA >"); } // obter o ESCOLHA da pilha NodeInstruction n = (NodeInstruction) stack.pop(); //ERRO if (n.GetType() != Keyword.ESCOLHA) { throw new LanguageException( pt.GetCharNum(), pt.GetText(), "O CICLO :\"" + n.GetText() + "\" ESTÁ ABERTO", " ESCREVA A INSTRUÇÃO QUE INDICA O FIM DO CICLO E NÃO \"" + pt.GetText() + "\""); } //FAZER O ESCOLHA pt = ExpandEscolhe.ExpandSWITCH(n, stack.size(), memory); cleanMemory(stack.size() + 1, memory); } else if (pt.GetType() == Keyword.PROCEDIMENTO || pt.GetType() == Keyword.FUNCAO || pt.GetType() == Keyword.CONSTRUTOR) { ExpandProcedimento.ExpandSUBRUTINA(rutina, pt, stack.size(), memory); } else if (pt.GetType() == Keyword.CHAMADOPROCEDIMENTO) { try { ExpandChamadoProcedimento.ExpandCHAMADO(rutina, pt, stack.size(), memory); } catch (LanguageException e) { if (e.line > 0 && !e.codeLine.isEmpty()) { throw e; } throw new LanguageException( pt.GetCharNum(), pt.GetText(), e.error, e.solution); } } else if (pt.GetType() == Keyword.CHAMADOPROCEDIMENTO) { ExpandChamadoProcedimento.ExpandCHAMADO(rutina, pt, stack.size(), memory); } else if (pt.GetType() == Keyword.DESCONHECIDO) { throw new LanguageException( pt.GetCharNum(), pt.GetText(), "INSTRUÇÃO DESCONHECIDA: " + pt.GetText(), "VERIFIQUE A INSTRUÇÃO"); } pt = pt.GetNext(); }// pt != null // - - -- ciclos nao fechados . . . . //David: troque el mensaje para que sea acorde con todas las estructuras, antes solo falaba ciclo, agora fala estructura if (!stack.isEmpty()) { NodeInstruction n = (NodeInstruction) stack.pop(); throw new LanguageException( n.GetCharNum(), n.GetText(), //"O CICLO NÃO ESTÁ FECHADO", "A ESTRUTURA " + Keyword.GetTextKey(n.GetType()) + " NÃO ESTÁ FECHADA.", "POR FAVOR, FECHE A ESTRUTURA COM FIM" + Keyword.GetTextKey(n.GetType())); } } //David: NOVO public static void ExpandRegisto(BloqueRegisto rutina) throws LanguageException { NodeInstruction pt = rutina.getStartNode(); TipoRegisto tipoRegisto; tipoRegisto = new TipoRegisto(); while (pt != null) { //fazer as variaveis if (pt.GetType() == Keyword.DEFINIR) { pt = ExpandDefinirSimbol.ExpandVariable(pt, 0, tipoRegisto.Defs); } else if (pt.GetType() == Keyword.REGISTO) { String name = pt.text.toUpperCase().replace("REGISTO ", "").trim(); tipoRegisto.Name = name; rutina.Nome = name; rutina.type = Bloque.REGISTO; for (int i = 0; i < Intermediario.tiposRegistos.size(); i++) { TipoRegisto tmp = (TipoRegisto) Intermediario.tiposRegistos.get(i); if (tmp.Name.equals(name)) { throw new LanguageException( "Já existe um registo com esse nome", "Mude o nome do registo"); //David: Revisar ortografia } } } else if (pt.GetType() == Keyword.FIMREGISTO) { Intermediario.tiposRegistos.add(tipoRegisto); } else { throw new LanguageException( "Uma declaração de tipo de dado registo só pode ter declaraçoes de variaveis", "Retire esta instrucção"); //David: Revisar ortografia } pt = pt.GetNext(); } } //David: NOVO public static void ExpandClasse(BloqueClasse rutina) throws LanguageException { NodeInstruction pt = rutina.getStartNode(); TipoClasse tipoClasse; tipoClasse = new TipoClasse(rutina); while (pt != null) { //fazer as variaveis if (pt.GetType() == Keyword.DEFINIR) { pt = ExpandDefinirSimbol.ExpandVariable(pt, 0, tipoClasse.Defs); } else if (pt.GetType() == Keyword.CLASSE) { String name = pt.text.toUpperCase().replace("CLASSE ", "").trim(); tipoClasse.Name = name; rutina.Nome = name; rutina.type = Bloque.CLASSE; for (int i = 0; i < Intermediario.tiposClasses.size(); i++) { TipoClasse tmp = Intermediario.tiposClasses.get(i); if (tmp.Name.equals(name)) { throw new LanguageException( "Já existe uma classe com esse nome", "Mude o nome da classe"); //David: Revisar ortografia } } } else if (pt.GetType() == Keyword.FIMCLASSE) { Intermediario.tiposClasses.add(tipoClasse); } else { throw new LanguageException( "Uma declaração de tipo de dado registo só pode ter declaraçoes de variaveis", "Tire esta instrucção"); //David: Revisar ortografia } pt = pt.GetNext(); } for (int i = 0; i < rutina.metodos.size(); i++) { ExpandProcedimento.ExpandSUBRUTINA(rutina.metodos.get(i), rutina.metodos.get(i).getStartNode(), 0, null); rutina.metodos.get(i).getStartNode().Expanded = true; } BloqueClasse ClaseAnterior = BloqueClasse.ClaseActualParaExpandir;//esto realmente não é preciso aqui, mais melhor fica BloqueClasse.ClaseActualParaExpandir = rutina; for (int i = 0; i < rutina.metodos.size(); i++) { ExpandSubrutine(rutina.metodos.get(i)); } if (rutina.Construtor != null) { ExpandSubrutine(rutina.Construtor); //o construtor não precisa expandir previamente como os outros metodos } BloqueClasse.ClaseActualParaExpandir = ClaseAnterior; } //----------------------------------------------------------------------------- //------------ -------------------- //------------ E S C R E V A E M O S T R E -------------------- //------------ ------------------- //----------------------------------------------------------------------------- protected static void VerifyWRITE(NodeInstruction node, Vector memory) throws LanguageException { String MOSTRAR = "MOSTRE"; int cont = 0; String ESCREVER = Keyword.GetTextKey(Keyword.ESCREVA); String instrucao = node.GetText().trim(); //verificar se a primeira palavra É "escreva String escr = instrucao.substring(0, ESCREVER.length()); if (!escr.equalsIgnoreCase(ESCREVER)) { cont = 1; escr = instrucao.substring(0, MOSTRAR.length()); if (!escr.equalsIgnoreCase(MOSTRAR)) { throw new LanguageException( node.GetCharNum(), node.GetText(), " ESPERAVA UM... " + ESCREVER, " VERIFICAR A INSTRUÇÃO"); } } if (cont == 0) { instrucao = instrucao.substring(ESCREVER.length()).trim(); } else { instrucao = instrucao.substring(MOSTRAR.length()).trim(); } //dividir as variaveis IteratorCodeParams tok = new IteratorCodeParams(instrucao, ","); while (tok.hasMoreElements()) { String elem = tok.current(); tok.next(); try { if (!Values.IsString(elem) && !Expressao.IsExpression(elem, memory)) { throw new LanguageException( node.GetCharNum(), node.GetText(), "O ELEMENTO \"" + elem + "\" NÃO É UM TEXTO OU UMA EXPRESSÃO VÁLIDA", " COLOQUE ASPAS NO ELEMENTO OU VERIFIQUE A EXPRESSÃO"); } } catch (Exception e) { if (e instanceof LanguageException) { if (((LanguageException)e).line > 0 && !((LanguageException)e).codeLine.isEmpty()) { throw e; } throw new LanguageException( node.GetCharNum(), node.GetText(), ((LanguageException)e).error, ((LanguageException)e).solution); } else { throw new LanguageException( node.GetCharNum(), node.GetText(), "O ELEMENTO \"" + elem + "\" NÃO É UMA EXPRESSÃO VÁLIDA", " VERIFIQUE A EXPRESSÃO"); } } } cont = 0; } //------------------------------------------------------------------------------ //------------ CALCULO -------------------- //------------------------------------------------------------------------------ public static void VerifyCalculate(NodeInstruction node, Vector memory) throws LanguageException { String str = node.GetText(); int pos = str.indexOf(Keyword.ATRIBUI); String name = str.substring(0, pos).trim(); String elem = str.substring(pos + Keyword.ATRIBUI.length()).trim(); ParteDeExpresion var = Variavel.getVariable(name, memory); if (var == null || !(var instanceof Simbolo)) { throw new LanguageException( node.GetCharNum(), str, " O SIMBOLO \"" + name + "\" NÃO ESTÁ DEFINIDO NA MEMÓRIA", " DEFINA O SÍMBOLO ANTES DE USAR"); } elem = NormalizeMinus(elem, memory); Object value = null; try { value = Expressao.Evaluate(elem, memory, true); } catch (Exception e) { throw new LanguageException( node.GetCharNum(), node.GetText(), " O VALOR DA EXPRESSÃO :" + elem, e.getMessage()); } // // if ( !Values.IsNumber(value)) if (!Simbolo.IsCompatible(var, value)) { throw new LanguageException( node.GetCharNum(), str, " O VALOR DA EXPRESSÃO :" + elem, " NÃO É COMPATÍVEL COM O TIPO DE DADO:" + ((Simbolo) var).getTypeLexema()); } node.SetText(name + " " + Keyword.ATRIBUI + " " + elem); } public static void VerifyRetorno(NodeInstruction node, Vector memory) throws LanguageException { String str = node.GetText().substring(Keyword.GetTextKey(Keyword.RETORNE).length()).trim(); try { if (!Expressao.IsExpression(str, memory)) { throw new LanguageException( node.GetCharNum(), node.GetText(), "O ELEMENTO \"" + str + "\" NÃO É UMA EXPRESSÃO VÁLIDA", " VERIFIQUE A EXPRESSÃO DO RETORNO"); } } catch (Exception e) { if (e instanceof LanguageException) { if (((LanguageException) e).line > 0 && !((LanguageException) e).codeLine.isEmpty()) { throw e; } throw new LanguageException( node.GetCharNum(), node.GetText(), ((LanguageException) e).error, ((LanguageException) e).solution); } else { throw new LanguageException( node.GetCharNum(), node.GetText(), "O ELEMENTO \"" + str + "\" NÃO É UMA EXPRESSÃO VÁLIDA", " VERIFIQUE A EXPRESSÃO DO RETORNO"); } } } public static String NormalizeMinus(String str, Vector memory) throws LanguageException { StringBuffer newExpr = new StringBuffer(); IteratorExpression tok = new IteratorExpression(str); Simbolo var; String elem; //se comecar pelo sinal menos if (tok.current().equals("-(")) { newExpr.append("-1 * ("); tok.next(); } while (tok.hasMoreElements()) { elem = tok.current(); tok.next(); newExpr.append(GetSafeElement(elem, memory)); } return newExpr.toString().trim(); } public static String GetSafeElement(String elem, Vector memory) throws LanguageException { ParteDeExpresion var; //------------------------- sinal - ------------- if (elem.charAt(0) == '-') { //--operador - if (elem.length() == 1) { return elem + " "; } //---resto String resto = elem.substring(1); var = Variavel.getVariable(resto, memory); //valor negativo if (var == null || var instanceof Operador) { return elem + " "; } // se for uma variavel com sinal - else { return " ( " + resto + " * -1 ) "; } } return elem + " "; } protected static void cleanMemory(int level, Vector memory) {//sbr for (int index = memory.size() - 1; index >= 0; index--) { Simbolo v = (Simbolo) memory.get(index); //elimina as variaveis superiores ou iguais ao nivel if (v.getLevel() >= level) { memory.remove(index); } else { break; } } } }