package Portugol.Language.Criar; import Portugol.Language.Analisador.Expressao; import Portugol.Language.Analisador.Keyword; import Portugol.Language.Utilitario.LanguageException; import java.util.StringTokenizer; import java.util.Vector; public class ExpandEscolhe { public static String VERSION = "Versão:2.0 \t(c)Augusto Bilabila e David Silva Barrera"; //------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------- public static NodeInstruction ExpandSWITCH(NodeInstruction switchNode, int level, Vector memory) throws LanguageException { //-----------------------------------------------------ESCOLHA -------- String line = switchNode.GetText().trim(); String ESCOLHE = Keyword.GetTextKey(Keyword.ESCOLHA); //palavra ESCOLHA String escolhe = line.substring(0, ESCOLHE.length()); // expressao de controle String expressaoEscolhe = line.substring(ESCOLHE.length()).trim(); if (!escolhe.equalsIgnoreCase(ESCOLHE)) { throw new LanguageException( switchNode.GetCharNum(), switchNode.GetText(), " Esperava o comando " + ESCOLHE, " VERIFICAR A SINTAXE DA ESTRUTURA DE CONTROLO"); } try { if (!Expressao.IsExpression(expressaoEscolhe, memory)) { throw new LanguageException( switchNode.GetCharNum(), switchNode.GetText(), expressaoEscolhe + " NÃO É UMA VARIÁVEL NEM EXPRESSÃO ", " VERIFIQUE A EXPRESSÃO " + ESCOLHE); } } catch (Exception e) { if (e instanceof LanguageException) { if (((LanguageException)e).line > 0 && !((LanguageException)e).codeLine.isEmpty()) { throw e; } throw new LanguageException( switchNode.GetCharNum(), switchNode.GetText(), ((LanguageException)e).error, ((LanguageException)e).solution); } else { throw new LanguageException( switchNode.GetCharNum(), switchNode.GetText(), expressaoEscolhe + " NÃO É UMA VARIÁVEL NEM EXPRESSÃO ", " VERIFIQUE A EXPRESSÃO " + ESCOLHE); } } //procurar o ultimo no do escolhe NodeInstruction end = switchNode.GetNext(); if (end.GetType() == Keyword.FIMESCOLHE) { throw new LanguageException( switchNode.GetCharNum(), switchNode.GetText(), " A INSTRUÇÃO ESCOLHA TEM DE TER CASOS E/OU DEFEITO", " ACrecente Casos na instrução"); } while (end != null && end.GetType() != Keyword.FIMESCOLHE) { end = end.GetNext(); } //se nao houver fim do ciclo if (end == null) { throw new LanguageException( switchNode.GetCharNum(), switchNode.GetText(), " Não existe, FIM ESCOLHA que fecha esta estrutura ", " Escreva um FIM ESCOLHA depois deste BLOCO"); } //----------------------------------- CASOS -------------------------- NodeInstruction tmp2, tmp1, oldDecision = null, nodeAnt = null; tmp1 = switchNode.GetNext(); //fazer todos os casos while (tmp1.GetType() != Keyword.FIMESCOLHE && tmp1.GetType() != Keyword.DEFEITO) { // se for um caso expandir if (tmp1.GetType() == Keyword.CASO) { //---------------------------------------Ligar o ultimo ao END if (nodeAnt != null) //se nao fo o primeiro caso { // anterior aponta para fim nodeAnt.SetNext(end); //se o falso apontar par o no TMP1, passa a apontar para fim if (nodeAnt.GetIfFalse() != null && nodeAnt.GetIfFalse() == tmp1) { nodeAnt.SetIfFalse(end); } //se o verdadeiro apontar par o no TMP1, passa a apontar para fim if (nodeAnt.GetIfTrue() != null && nodeAnt.GetIfTrue() == tmp1) { nodeAnt.SetIfTrue(end); } } String tmp1_txt = tmp1.GetText(); tmp2 = ExpandCase(tmp1, level, memory, expressaoEscolhe, end); if (tmp2.GetType() == Keyword.CASO || tmp2.GetType() == Keyword.DEFEITO) { throw new LanguageException( tmp1.GetCharNum(), tmp1_txt, " O " + tmp1_txt + " não tem instruções ", " Acrecente instruções no CASO"); } //actualizar o ponteiro da condicao anterior if (oldDecision == null) { switchNode.SetNext(tmp1); } else { oldDecision.SetIfFalse(tmp1); } //actualizar a condicao anterior oldDecision = tmp1; // colocar o tmp1 no next tmp1 = tmp2; } //senao actualizar o nivel else { tmp1.IncrementLevel(); } nodeAnt = tmp1; //passar para a frente tmp1 = tmp1.GetNext(); } if (oldDecision == null) { throw new LanguageException( switchNode.GetCharNum(), switchNode.GetText(), " Não existe, CASO nesta estrutura ", " Escreva um CASO depois do Escolha"); } //--------------------------- actualizar os ponteiro do ultimo caso // anterior aponta para fim nodeAnt.SetNext(end); //se o falso apontar par o no TMP1, passa a apontar para fim if (nodeAnt.GetIfFalse() != null && nodeAnt.GetIfFalse() == tmp1) { nodeAnt.SetIfFalse(end); } //se o verdadeiro apontar par o no TMP1, passa a apontar para fim if (nodeAnt.GetIfTrue() != null && nodeAnt.GetIfTrue() == tmp1) { nodeAnt.SetIfTrue(end); } //------------------------------------------------------Fazer o default if (tmp1.GetType() == Keyword.DEFEITO) { NodeInstruction tmpd = tmp1; tmp1 = ExpandDefaultCase(tmp1, level, memory, expressaoEscolhe, end); if (tmp1.GetType() == Keyword.FIMESCOLHE) { throw new LanguageException( tmpd.GetCharNum(), tmpd.GetText(), " O DEFEITO não tem instruções ", " Acrecente instruções no CASO por DEFEITO"); } oldDecision.SetIfFalse(tmp1); while (tmp1.GetType() != Keyword.FIMESCOLHE) { tmp1.IncrementLevel(); tmp1 = tmp1.GetNext(); } } //fazer um no de juncao tmp1.SetType(Keyword.CONECTOR); //fim do escolhe return tmp1; } //------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------- private static NodeInstruction ExpandDefaultCase(NodeInstruction defaultNode, int level, Vector memory, String expressaoEscolhe, NodeInstruction end) throws LanguageException { String line = defaultNode.GetText().trim(); //defeito tem 7 letras String strCaso = line.substring(0, 7); if (!strCaso.equalsIgnoreCase("DEFEITO")) { throw new LanguageException( defaultNode.GetCharNum(), defaultNode.GetText(), " Esperava um, DEFEITO : intruções", " ???? "); } int indexPontos = line.indexOf(':'); if (indexPontos < 0) { throw new LanguageException( defaultNode.GetCharNum(), defaultNode.GetText(), " Esperava um DEFEITO \":\" intruções", " Coloque os dois pontos : ao DEFEITO"); } //------------------------------------------ FAZER A PRIMEIRA INSTRUCAO //import buscar a intruçao String instrucao = line.substring(indexPontos + 1).trim(); // no da intruçao NodeInstruction nodeInstr; //fazer um novo no if (instrucao.length() > 0) { nodeInstr = new NodeInstruction(instrucao, defaultNode.GetCharNum(), level + 1); } else { nodeInstr = defaultNode.GetNext(); } return nodeInstr; } //------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------- private static NodeInstruction ExpandCase(NodeInstruction caseNode, int level, Vector memory, String expressaoEscolhe, NodeInstruction end) throws LanguageException { String line = caseNode.GetText().trim(); //caso tem 4 letras String strCaso = line.substring(0, 4); if (!strCaso.equalsIgnoreCase("CASO")) { throw new LanguageException( caseNode.GetCharNum(), caseNode.GetText(), " Esperava um CASO [expressao] : intrucoes", " Depois do comando ESCOLHA vem um CASO "); } int indexPontos = line.indexOf(':'); if (indexPontos < 0) { throw new LanguageException( caseNode.GetCharNum(), caseNode.GetText(), " Esperava um CASO [expressao] \":\" intrucoes", " Coloque os dois pontos : depois da expressao"); } //---------------------------------------------------------------- //------- condicoes multiplas no CASO exp, exp, exp : -------- //---------------------------------------------------------------- // expressao da condicao (multipla) StringBuffer condicaoCaso = new StringBuffer(); // expressao simples do caso String expressaoCaso = ""; // expressao do caso String todasCaso = line.substring(4, indexPontos).trim(); //as condicoes no caso estao separadas por virgulas StringTokenizer tok = new StringTokenizer(todasCaso, ","); while (tok.hasMoreElements()) { expressaoCaso = tok.nextToken().trim(); //verificar se nao uma variavel ou expressao try { if (!Expressao.IsExpression(expressaoCaso, memory)) { throw new LanguageException( caseNode.GetCharNum(), caseNode.GetText(), expressaoCaso + " NÃO É UMA VARIÁVEL NEM EXPRESSÃO ", " VERIFIQUE A EXPRESSÃO DO <ESCOLHA>"); } } catch (Exception e) { if (e instanceof LanguageException) { if (((LanguageException)e).line > 0 && !((LanguageException)e).codeLine.isEmpty()) { throw e; } throw new LanguageException( caseNode.GetCharNum(), caseNode.GetText(), ((LanguageException)e).error, ((LanguageException)e).solution); } else { throw new LanguageException( caseNode.GetCharNum(), caseNode.GetText(), expressaoCaso + " NÃO É UMA VARIÁVEL NEM EXPRESSÃO ", " VERIFIQUE A EXPRESSÃO DO <ESCOLHA>"); } } //adicionar uma nova condicao condicaoCaso.append(expressaoEscolhe + " = " + expressaoCaso); // adicionar a condicao OU caso haja mais elementos if (tok.hasMoreElements()) { condicaoCaso.append(" OU "); } } //---------------------------------------------------------------- //--------------- FAZER A PRIMEIRA INSTRUCAO ------------------------ //---------------------------------------------------------------- //import buscar a intrucao String instrucao = line.substring(indexPontos + 1).trim(); // no da intrucao NodeInstruction nodeInstr; //fazer um novo no if (instrucao.length() > 0) { nodeInstr = new NodeInstruction(instrucao, caseNode.GetCharNum(), level + 1); nodeInstr.SetNext(caseNode.GetNext()); } else { nodeInstr = caseNode.GetNext(); nodeInstr.IncrementLevel(); } //-------------------------------------------------------ALTERAR O CASO //alterar o no para ser um IF caseNode.SetLevel(level); // retirar o CASO e o : caseNode.SetText(condicaoCaso.toString()); // defenir o tipo caseNode.SetType(Keyword.SE); // actualizar os ponteiros next e false para end; caseNode.SetNext(end); caseNode.SetIfFalse(end); //ligar o verdadeiro a intrucao caseNode.SetIfTrue(nodeInstr); // retorna um o com a intrucao seguinte return nodeInstr; } }