package Portugol.Language.Criar; import Editor.Utils.FileManager; import Portugol.Language.Analisador.Keyword; import Portugol.Language.Analisador.TipoClasse; import Portugol.Language.Consola.ConsoleIO; import java.util.StringTokenizer; import java.util.Vector; import Portugol.Language.Utilitario.LanguageException; /** * @author Augusto Bilabila original de Antonio manso */ public class Intermediario { public static String VERSION = "Versão:2.0 \t(c)Augusto Bilabila e David Silva Barrera"; static public Vector<BloqueSubrutine> subrutinas; static public Vector tiposRegistos = new Vector(); static public Vector<TipoClasse> tiposClasses = new Vector(); private BloqueSubrutine Inicio; public static ConsoleIO console; public BloqueSubrutine getInicio() { return Inicio; } /** * Constroi um fluxograma * * @param code programa fonte * @throws Portugol.Language.Utils.LanguageException excepcao */ public Intermediario(String code) throws LanguageException { Construir(code); } /** * constroi um fluxograma com um ficheiro de programa * * @param filename no do ficheiro * @throws Portugol.Language.Utils.LanguageException erro */ public void ReadFile(String filename) throws LanguageException { FileManager f = new FileManager(); Construir(f.ReadFile(filename)); } /** * Controi o fluxograma * * @param programa Texto do programa * @throws Portugol.Language.Utils.LanguageException erro */ protected void Construir(String programa) throws LanguageException { subrutinas = new Vector<BloqueSubrutine>(); tiposRegistos = new Vector(); tiposClasses = new Vector(); int charNum = 0; int positionY = 0; Bloque rutina = null; BloqueClasse claseActual = null; String instruction; //System.out.print("programa \n" + programa); // as intrucoes terminam com enter StringTokenizer st = new StringTokenizer(programa, "\n\r"); //no anterior (para fazer a ligacao) NodeInstruction previousNode = null; // novo nó NodeInstruction newNode = null; //fazer a lista seguida while (st.hasMoreTokens()) { instruction = st.nextToken(); //contar o numero de caracteres charNum += instruction.length() + 1; // terminador //retirar espacos e comentarios instruction = RemoveComentarios(instruction); //se for uma linha vazia if (instruction.length() == 0) { continue; } newNode = new NodeInstruction(instruction, charNum - 1, 0); newNode.SetPositionY(++positionY); if (newNode.GetType() == Keyword.DEFINIR) { if (!newNode.GetText().contains(",")) { if (newNode.GetText().startsWith("literal ") && !newNode.GetText().endsWith("\"")) { newNode.SetText(newNode.GetText() + "<-\"\""); } } } switch (newNode.GetType()) { case Keyword.INICIO: case Keyword.PROCEDIMENTO: case Keyword.FUNCAO: case Keyword.CONSTRUTOR: if (rutina != null) { throw new LanguageException( newNode.GetCharNum(), newNode.GetText(), "AINDA EM OTRO BLOCO DE CODIGO", "DEBE ENCERRAR O BLOCO"); //David: Correguir ortografia } if ((newNode.GetType() == Keyword.INICIO) && claseActual != null) { throw new LanguageException( newNode.GetCharNum(), newNode.GetText(), "O BLOCO DE INICIO NÃO PODE ESTAR CONTIDO NUMA CLASSE", "MUDE O CÓDIGO"); //David: Correguir ortografia } if ((newNode.GetType() == Keyword.CONSTRUTOR) && claseActual == null) { throw new LanguageException( newNode.GetCharNum(), newNode.GetText(), "O BLOCO DE CONSTRUÇÃO PRECISA ESTAR CONTIDO NUMA CLASSE", "MUDE O CÓDIGO"); //David: Correguir ortografia } rutina = new BloqueSubrutine(); rutina.start = newNode; rutina.Nome = instruction; previousNode = rutina.start; if ((newNode.GetType() == Keyword.INICIO)) {//David: debe ser igual para que arranque por INICIO Inicio = (BloqueSubrutine) rutina; } else { if (claseActual == null) { subrutinas.add((BloqueSubrutine) rutina); } else { if ((newNode.GetType() == Keyword.CONSTRUTOR)) {//David: debe ser igual para que arranque por INICIO claseActual.Construtor = (BloqueSubrutine) rutina; } else { claseActual.metodos.add((BloqueSubrutine) rutina); } previousNode = rutina.start; } } break; case Keyword.REGISTO: if (rutina != null) { throw new LanguageException( newNode.GetCharNum(), newNode.GetText(), "AINDA EM OTRO BLOCO DE CODIGO", "DEBE ENCERRAR O BLOCO"); //David: Correguir ortografia } if (claseActual != null) { throw new LanguageException( newNode.GetCharNum(), newNode.GetText(), "NO COMPALG NÂO PODE DECLARAR REGISTOS DENTRO DAS CLASSES", "MUDE O CÓDIGO"); //David: Correguir ortografia } rutina = new BloqueRegisto(); rutina.start = newNode; previousNode = rutina.start; rutina.Nome = instruction; break; case Keyword.CLASSE: if (rutina != null) { throw new LanguageException( newNode.GetCharNum(), newNode.GetText(), "AINDA EM OTRO BLOCO DE CODIGO", "DEBE ENCERRAR O BLOCO"); //David: Correguir ortografia } if (claseActual != null) { throw new LanguageException( newNode.GetCharNum(), newNode.GetText(), "NO COMPALG NÂO PODE DECLARAR CLASSES DENTRO DE CLASSES", "MUDE O CÓDIGO"); //David: Correguir ortografia } claseActual = new BloqueClasse(); rutina = null;//redundante claseActual.start = newNode; previousNode = claseActual.start; claseActual.lastNode = previousNode; claseActual.Nome = instruction; break; case Keyword.FIM: case Keyword.FIMPROCEDIMENTO: case Keyword.FIMFUNCAO: case Keyword.FIMCONSTRUTOR: previousNode.SetNext(newNode); previousNode = newNode; if (claseActual == null) { ExpandFluxogram.ExpandSubrutine((BloqueSubrutine) rutina); } else { ((BloqueSubrutine) rutina).classePae = claseActual; } rutina = null; break; case Keyword.FIMREGISTO: previousNode.SetNext(newNode); previousNode = newNode; ExpandFluxogram.ExpandRegisto((BloqueRegisto) rutina); rutina = null; break; case Keyword.FIMCLASSE: if (claseActual == null) { throw new LanguageException( newNode.GetCharNum(), newNode.GetText(), "NÃO TEM UMA CLASSE PARA ENCERRAR", "MUDE O CÓDIGO"); //David: Correguir ortografia } claseActual.lastNode.SetNext(newNode); previousNode = newNode; ExpandFluxogram.ExpandClasse(claseActual); claseActual = null; rutina = null; break; default: if (claseActual != null && rutina == null) { previousNode = claseActual.lastNode; } previousNode.SetNext(newNode); previousNode = newNode; if (claseActual != null && rutina == null) { claseActual.lastNode = newNode; //newNode.level++; } break; } }//fim da lista seguida } //============================================================================= public String RemoveComentarios(String str) { StringBuffer newStr = new StringBuffer(); boolean isComented = false;//David: Ojo, ver impacto de traer esta variable para aqui, desde Subrutine for (int index = 0; index < str.length(); index++) { switch (str.charAt(index)) { case '/': // comentario "//" if (index + 1 < str.length() && str.charAt(index + 1) == '/') { return newStr.toString().trim(); } //inicio de um comentario /* if (index + 1 < str.length() && str.charAt(index + 1) == '*') { isComented = true; } else //fim do comentario */ if (index > 0 && str.charAt(index - 1) == '*') { isComented = false; } //introduz caracter / else { newStr.append(str.charAt(index)); } break; default: // se nao for comentario if (!isComented) { newStr.append(str.charAt(index)); } } } return newStr.toString().trim(); } /** * calcula o texto de um nodo * * @param node nodo de origem * @return o texto de um nodo */ public static String GetCode(NodeInstruction node) {//im if (node.GetType() == Keyword.CONECTOR) { return ""; } if (node.GetType() == Keyword.SE) { return ExpandSe.toString(node); } if (node.GetType() == Keyword.ENQUANTO) { return ExpandEnquanto.toString(node); } return node.toString() + "\n"; } }