/* * Classe que trata sobre as funções que o utilizador poderá utilizar... * Esta classe é muito com a classe procedimento com o detalhe de retornar * sempre um valor específico. */ package Portugol.Language.Calcular; import Portugol.Language.Criar.NodeInstruction; import Portugol.Language.Analisador.Keyword; import Portugol.Language.Utilitario.LanguageException; import java.util.StringTokenizer; import java.util.Vector; import javax.swing.JOptionPane; /** * @author Augusto Bilabila 08-02-2012 */ public class Funcao { public static String VERSION = "Versão:2.0 \t(c)Augusto Bilabila e David Silva Barrera"; private String algol="",Novoalgol=""; Vector acumulafuncao = new Vector(); Vector acumulaTipofuncao = new Vector(); Vector acumulaInst = new Vector(); Vector acumulaSimb = new Vector(); int contInst = 0; byte controlaFuncao = 0; String strInteiro ="",strReal ="",strLiteral ="",strLogico ="",strCaracter =""; String []tipos = {"inteiro","real","logico","literal","caracter"}; Keyword palavraChave; public Funcao(String programa) { algol= programa; } public String getNovoalgol() { return Novoalgol; } public void setNovoalgol(String Novoalgol) { this.Novoalgol = Novoalgol; } public String getAlgol() { return algol; } public void setAlgol(String algol) { this.algol = algol; } public String VariaveisTipo(String var){ int av = -1; av = strInteiro.indexOf(var); if(av!=-1) return "inteiro "; av = strReal.indexOf(var); if(av!=-1) return "real "; av = strLiteral.indexOf(var); if(av!=-1) return "literal "; av = strLogico.indexOf(var); if(av!=-1) return "logica "; // av = strCaracter.indexOf(var); if(av!=-1) return "char "; return "N"; } //-------------------------------------------------------------------- public String RemoverCaract(String str){ str = str.replace(',', ' '); str = str.replace(')', ' '); str = str.trim(); return str; } //-------------------------------------------------------------------- public String RemoveAspas(String str){ int pos=0,qtd1=0; String str1=""; for(int i=0;i<str.length();i++){ String a=""+str.charAt(i); if(a.endsWith("\"")) {qtd1++;} if(qtd1==1) { str1+=str.charAt(i); } } if(str1.length()>1){ String simbolo = "*%-%*"+contInst; str1 = str1.replace("\"", ""); str = str.replace(str1, simbolo); acumulaInst.add(str1); acumulaSimb.add(simbolo); contInst++; } return str; } //-------------------------------------------------------------------------- public String DevolveAspas(String str){ for(int i=0;i<acumulaSimb.size();i++){ int k = str.indexOf(""+acumulaSimb.get(i)) ; if(k!=-1){ str = str.replace(""+acumulaSimb.get(i), ""+acumulaInst.get(i)); } } return str; } //---------- Metodo que substitui o valor do argumento no parametro -------- public String SubstituirVar(String var1,String var2,String instrucao){ var1 = (var1.substring(var1.indexOf(" "))).trim(); StringTokenizer st = new StringTokenizer(instrucao,"\n"); NodeInstruction node=null; String linha=""; String straux = "",instrucaoaux = ""; while (st.hasMoreTokens()) { linha = st.nextToken(); node = new NodeInstruction(linha,0,0); instrucaoaux += RemoveAspas(node.GetText())+"\n"; } for(int i=0;i<instrucaoaux.length();i++){ String a=""+instrucaoaux.charAt(i); if(a.equals(" ")){ straux =""; }else{ straux +=a; } straux = straux.trim(); if(straux.equals(var1)){ instrucaoaux = instrucaoaux.replace(straux, var2); } } return instrucaoaux; } //-------------------------------------------------------------------------- public void VerOcorrencia_funcao() throws LanguageException{ for(int i=0;i<acumulafuncao.size();i++){ for(int j=0;j<acumulafuncao.size();j++){ if(i!=j) if((subst(""+acumulafuncao.get(i))).equals((subst(""+acumulafuncao.get(j))))) throw new LanguageException( " O COMPILADOR DETECTOU FUNÇÕES COM O MESMO NOME\n", "DEVE MUDAR O NOME DO DESTA FUNÇÃO: " + acumulafuncao.get(i) +""); } } } //-------------------------------------------------------------------------- /*Verifica se o tipo de retorno esta bem definido na funcao*/ public void controlatipo_funcao(String tipo,NodeInstruction node) throws LanguageException{ int j = -1; for(int i=0;i<tipos.length;i++){ if(tipos[i].equals(tipo)){ j = i; i = tipos.length; } } if (j!=-1){ acumulaTipofuncao.add(tipos[j]); } else throw new LanguageException(node.GetCharNum(),node.GetText(), " O COMPILADOR ESPERAVA UM TIPO DE DADO PRIMITIMO ANTES DO NOME DA FUNÇÃO\n", "COLOQUE O TIPO DE RETORNO DA FUNÇÃO ENTRE A PALAVRA FUNÇÃO E O NOME DA FUNÇÃO\n" + "OS TIPOS PRIMITIVOS SÃO: inteiro,real,logico,literal e caracter"); } //------------------------------------------------------------------------- public String subst(String str){ str = str.substring(0, str.indexOf("(")); return str; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ public String Tratar_funcao() throws LanguageException { StringTokenizer st = new StringTokenizer(getAlgol(),"\n\r"); NodeInstruction node=null; String linha=""; String str = "",str1 = ""; Vector instrucpro = new Vector(); int cont = 0, contapro =0; while (st.hasMoreTokens()) { linha = st.nextToken(); node = new NodeInstruction(linha,0,0); if(controlaFuncao == 1){ if (node.GetType() == Keyword.DESCONHECIDO){ str = node.GetText(); int index = acumulafuncao.indexOf(str); if(index != -1 && cont == 2){ algol = algol.replace(str,""+instrucpro.get(index)+"\nretorna_retorno ( id )"); } else{ if(str.indexOf('(')!=-1){ int t=0; String sta ="",stb="",st3="",param1=""; sta = str.substring(0, str.indexOf('(')); for(int i =0; i<acumulafuncao.size();i++){ if((""+acumulafuncao.get(i)).startsWith(sta)){ t=1; st3 = ""+acumulafuncao.get(i); // guarda a instrucao i=acumulafuncao.size(); } } if(t!=1) throw new LanguageException( node.GetCharNum(), node.GetText(), " ESTA FUNÇÃO É UNEXISTENTE", "TENTA VERIFICAR BEM NOME DA FUNÇÃO " + sta +"\nOU SE POSSUE ALGUM PARAMETRO"); stb = st3.substring(str.indexOf('(')); // tira os parametros na declaracao param1 = str.substring(str.indexOf('(')); // tira os argumentos na utilizacao int p1 = 0,p2 = 0; for(int i =0; i<stb.length();i++){ if(stb.charAt(i)==',') p1++; } for(int i =0; i<param1.length();i++){ if(param1.charAt(i)==',') p2++; } if(p1!=p2) throw new LanguageException( node.GetCharNum(), node.GetText(), " NUMERO DE ARGUMENTO INCORRECTO", "VERIFICA COMO CONSTRUIU ESTA FUNÇÃO ("+ sta +"), QUANTO AO PARÁMETRO"); else{ String strp = "",strp1 = ""; int v1=0,i1=1,i2=1; String inst = ""; do{ for(int i =i1; i<stb.length();i++){ if(stb.charAt(i)!=','||stb.charAt(i)!=')'){ strp +=stb.charAt(i); } if (stb.charAt(i)==','||stb.charAt(i)==')') { v1++; i1 = i+1; i=stb.length(); //forca o termino do ciclo } } for(int f =i2; f<param1.length();f++){ if(param1.charAt(f)!=','||param1.charAt(f)!=')'){ strp1 +=param1.charAt(f); } if (param1.charAt(f)==','||param1.charAt(f)==')') { i2 = f+1; f=param1.length(); //forca o termino do ciclo } } strp = RemoverCaract(strp); strp1 = RemoverCaract(strp1); String tipo = VariaveisTipo(strp1); //retorna o tipo da variavel if(!strp.startsWith(tipo)) //verifica se o argumento tem um tipo diferente do parametro throw new LanguageException( node.GetCharNum(), node.GetText(), " O TIPO DE DADO DO ARGUMENTO NÃO É COMPATIVEL COM O PARÂMETRO\n", "VERIFICA COMO ESTÁ DEFINIDO OS PARAMETROS DA FUNÇÃO ("+ sta +")"); //Substituir as variaveis do funçao(parametro) index = -1; for (int j=0;j<acumulafuncao.size();j++){ String a = ""+acumulafuncao.get(j); if(a.startsWith(sta)) index = j; } if(index != -1 && cont == 2){ inst = ""+instrucpro.get(index); } inst = (SubstituirVar(strp,strp1,inst)); instrucpro.set(index, inst); inst = (DevolveAspas(inst)); strp = ""; strp1 = ""; }while(v1<=p1); inst = (DevolveAspas(inst)); instrucpro.set(index, inst); algol = algol.replace(str,""+instrucpro.get(index)+""); } } } } } //----------------- Tipo de dado Primitivo ---------------------- if (node.GetType() == Keyword.DEFINIR){ String stri = ""+node.GetText(); // separa as variaveis por tipo int contInt = stri.indexOf("inteiro "); int contFloat = stri.indexOf("real "); int contString = stri.indexOf("literal "); int contChar = stri.indexOf("caracter "); int contBoolean = stri.indexOf("logico "); if(contInt!=-1) strInteiro += stri; if(contFloat!=-1) strReal += stri; if(contString!=-1) strLiteral += stri; if(contChar!=-1) strLogico += stri; if(contBoolean!=-1) strCaracter += stri; } //------------------------------------------------------------------ if (node.GetType() == Keyword.INICIO){ VerOcorrencia_funcao(); } //***************************************************************** if(cont == 1 && (node.GetType() != Keyword.FIMFUNCAO)){ str1 += node.GetText()+"\n"; } //***************************************************************** if(cont == 2){ instrucpro.add(str1+"\n"); str1 = ""; } if (node.GetType() == Keyword.FUNCAO){ String algolAux = algol.substring(0,algol.indexOf("inicio")); algol = algol.replace(algolAux, "+00+00"); // muda temporariamente o algoritmo str = node.GetText(); String parte1 = (str.substring(6)).trim(); String str_tipo = (parte1.substring(0,parte1.indexOf(' '))).trim(); // Pega o tipo de retorno // JOptionPane.showMessageDialog(null, "Tipo ="+str_tipo); controlatipo_funcao(str_tipo,node); // Verifica se o utilicador colocou um tipo valido int c1 = parte1.indexOf(' '); if(c1 == -1 ) throw new LanguageException( node.GetCharNum(), node.GetText(), " A SINTAXE DA FUNÇÃO ESTÁ MAL CONSTRUIDA\n", "CONSULTE A AJUDA DO COMPILADOR, (pressione a tecla F1)"); String nomeFunc = (parte1.substring(c1)).trim();// Pega o nome da funcao palavraChave = new Keyword(); if(palavraChave.IsKeyword(nomeFunc.substring(0, nomeFunc.indexOf("(")).trim())) throw new LanguageException( node.GetCharNum(), node.GetText(), " O NOME DA FUNÇÃO NÃO PODE SER UMA PALAVRA RESERVADA\n", "MUDA O NOME DA FUNÇÃO "); acumulafuncao.add(nomeFunc); // guarda o nome da funcao algolAux = algolAux.replace("funcao ", "/*funcao "); // faz a alteracao algol = algol.replace("+00+00",algolAux); // volta no algoritmo anterior ja com a mudanca cont = 1; contapro++; } //****************************************************************** if (node.GetType() == Keyword.FIMFUNCAO){ algol = algol.replace("fimfuncao", "fimfuncao*/"); cont = 2; controlaFuncao = 1; } //****************************************************************** if (cont == 1 && node.GetType() == Keyword.RETORNE){ String str2 = node.GetText(); String a = (str2.substring(str2.indexOf(" "))).trim(); // obtem a variavel de retorno String tipo = VariaveisTipo(a); // JOptionPane.showMessageDialog(null, "Tipo ="+tipo); } } return algol; } }