package Portugol.Language.Criar;
import Portugol.Language.Analisador.Expressao;
import Portugol.Language.Analisador.Keyword;
import Portugol.Language.Analisador.Simbolo;
import Portugol.Language.Analisador.TipoDeParametro;
import Portugol.Language.Analisador.Variavel;
import Portugol.Language.Utilitario.LanguageException;
import java.util.Vector;
import javax.swing.JOptionPane;
public class ExpandProcedimento {
public static String VERSION = "Versão:2.0 \t(c)Augusto Bilabila e David Silva Barrera";
/**
* expande o ciclo
*
* @param begin nodo de inicip
* @param level nivel
* @param memory vector de memoria
* @throws Portugol.Language.Utils.LanguageException erro
*/
public static void ExpandSUBRUTINA(BloqueSubrutine rutina, NodeInstruction begin, int level, Vector memory)
throws LanguageException {
//string das instrucoes
if (begin.Expanded) {
return;
}
String exp = Normalize(begin.GetText());//David:
int endExp = exp.indexOf("(");
if (endExp < 0) {
throw new LanguageException(
begin.GetCharNum(), begin.GetText(),
"A Chamada não tem parêntese aberto", //David: revisar ortografia
"Coloque o parêntese \"(\" depois da chamada do procedimento");
}
// SE ocupa dois caracteres
String nome_proced = begin.GetText().substring(0, endExp).trim();
if (nome_proced.toUpperCase().startsWith(Keyword.GetTextKey(Keyword.PROCEDIMENTO))) {
rutina.type = Bloque.PROCEDIMENTO;
rutina.Nome = nome_proced.substring((Keyword.GetTextKey(Keyword.PROCEDIMENTO)+" ").length()).trim();// toUpperCase().replace("PROCEDIMENTO ", "").trim();
rutina.TipoRetorno = "";
} else if (nome_proced.toUpperCase().startsWith(Keyword.GetTextKey(Keyword.CONSTRUTOR))) {
rutina.type = Bloque.CONSTRUTOR;
rutina.Nome = nome_proced.substring((Keyword.GetTextKey(Keyword.CONSTRUTOR)+" ").length()).trim();// toUpperCase().replace("CONSTRUTOR ", "").trim();
rutina.TipoRetorno = rutina.Nome;
} else if (nome_proced.toUpperCase().startsWith(Keyword.GetTextKey(Keyword.FUNCAO))) {
rutina.type = Bloque.FUNCAO;
nome_proced = nome_proced.substring((Keyword.GetTextKey(Keyword.FUNCAO)+" ").length()).trim();// toUpperCase().replace("FUNCAO ", "").trim();
int beg = nome_proced.length() - 1;
while (beg > 0 && nome_proced.charAt(beg) != ' ') {
beg--;
}
rutina.Nome = nome_proced.substring(beg, nome_proced.length()).trim();
rutina.TipoRetorno = nome_proced.substring(0, beg).trim();
} else {
throw new LanguageException(
"Deve que utilizar PROCEDIMENTO, FUNCAO ou CONSTRUTOR",
"Mude a declaração"); //David: revisar ortografia
}
//Procesar os parametros
String parametros = begin.GetText().substring(endExp, begin.GetText().length()).trim();
String str = parametros.replace('(', (char) (32)).replace(')', (char) (32)).trim();
if (str.contains("<-") || str.contains("{") || str.contains("}")) {
throw new LanguageException(
begin.GetCharNum(), begin.GetText(),
"O CompAlg não aceita valores por defeito nos parâmetros",
"Tire a assinação do valor por defeito");
}
String SEPARATORS = ",";//David: virgula e espacio
String PERMITIDOS = "abcdefghijkmnlopqrstuvwxyzABCDEFGHIJKMNLOPQRSTUVWXYZ0123456789_[]& ";//David: virgula e espacio
int beg = 0;
//while( beg < str.length() && SEPARATORS.indexOf(str.charAt(beg))>=0 )
//quitar los posibles espacios iniciales
while (beg < str.length() && str.charAt(beg) == ' ') {
beg++;
}
int end = beg;
String tempStr = "";
String fullStr = "";
int contarParamProcesado = 1;
while (end < str.length()) {
if (SEPARATORS.indexOf(str.charAt(end)) >= 0) {
if (str.trim().length() > 0 && tempStr.trim().isEmpty()) {
throw new LanguageException(
begin.GetCharNum(), begin.GetText(),
"O parâmetro " + Integer.toString(contarParamProcesado) + " ficou vazio",
"Tire uma vírgula o complete o código"); //David:Revisar ortografia
}
AddParameter(rutina, begin, tempStr);
contarParamProcesado++;
end = end + 1;
tempStr = "";
} else {
if (PERMITIDOS.indexOf(str.charAt(end)) >= 0) {
tempStr = tempStr + str.charAt(end);
fullStr = tempStr + str.charAt(end);
}
end++;
}
}
if (fullStr.trim().length() > 0 && tempStr.trim().isEmpty()) {
throw new LanguageException(
begin.GetCharNum(), begin.GetText(),
"O parâmetro " + Integer.toString(contarParamProcesado) + " ficou vazio",
"Tire uma vírgula o complete o código"); //David:Revisar ortografia
}
AddParameter(rutina, begin, tempStr);
//Agregar atributos ao metodo
if (rutina.classePae != null) {
NodeInstruction node = rutina.getStartNode(); //primeiro nodo da rutina, depois da declaracion (nome e parametros)
NodeInstruction pt = rutina.classePae.start.GetNext();//pegar a instruçao depois da clase, deve ser atributo
while (pt != null && pt.GetType() != Keyword.FIMCLASSE) {
NodeInstruction copia = new NodeInstruction(pt);
copia.SetNext(node.GetNext());
node.SetNext(copia);
copia.EsReferencia = true;
pt = pt.GetNext();
}
}
}
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
/**
* texto do ciclo
*
* @param begin nodo de inicio
* @return texto do ciclo
*/
public static String toString(NodeInstruction begin) {
StringBuffer str = new StringBuffer();
str.append(begin.toString() + "\n");
NodeInstruction tmp = begin.GetIfTrue();
NodeInstruction end = begin.GetNext();
while (tmp != end) {
str.append(Intermediario.GetCode(tmp));
tmp = tmp.GetNext();
}
str.append("\n");
tmp = begin.GetIfFalse();
while (tmp != end) {
str.append(Intermediario.GetCode(tmp));
tmp = tmp.GetNext();
}
str.append(end.toString() + "\n");
return str.toString();
}
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
public static void CalculatePositions(NodeInstruction begin, double Y, double X) {
double PY, PX;
PX = 0.5 / (begin.level + 1.0);
begin.SetPositionY(Y);
begin.SetPositionX(X);
NodeInstruction tmp = begin.GetIfTrue();
//fazer o if
PY = Y + 1;
NodeInstruction end = begin.GetNext();
while (tmp != end) {
// FluxogramVisual.ProcessNodePosition(tmp, PY , X + PX);
PY = tmp.GetPositionY() + 1;
tmp = tmp.GetNext();
}
// posicao Y do conector
end.SetPositionY(PY);
// fazer o else
tmp = begin.GetIfFalse();
PY = Y + 1;
while (tmp != end) {
// FluxogramVisual.ProcessNodePosition(tmp,PY , X - PX);
PY = tmp.GetPositionY() + 1;
tmp = tmp.GetNext();
}
//conector ( calcular o maximo dos ys do if e do else
if (end.GetPositionY() < PY) {
end.SetPositionY(PY);
}
//posicao X do conector
end.SetPositionX(X);
}
//David: Agregado para permitir que se identifique ENTÃO con acento
static private String from = "ãõáéíóúàèìòùâêîôûÁÉÍÓÚÀÈÌÒÙÃÕÂÊÎÔÛçÇ";
static private String to = "AOAEIOUAEIOUAEIOUAEIOUAEIOUAOAEIOUCC";
public static String Normalize(String str) {
StringBuffer tmp = new StringBuffer();
int index;
for (int i = 0; i < str.length(); i++) {
index = from.indexOf(str.charAt(i));
if (index == -1) {
tmp.append(str.charAt(i));
} else {
tmp.append(to.charAt(index));
}
}
return tmp.toString().trim().toUpperCase();
}
private static void AddParameter(BloqueSubrutine rutina, NodeInstruction begin, String tempStr)
throws LanguageException {
if (!tempStr.isEmpty()) {
String PERMITIDOS = "abcdefghijkmnlopqrstuvwxyzABCDEFGHIJKMNLOPQRSTUVWXYZ0123456789_";//David: virgula e espacio
//David: provocar la creacion de la variable como un instruccion mas, cuando esto ocurra va a verificar si es parametro para tomar el valor del parametro en el chamado
NodeInstruction node = new NodeInstruction(tempStr.replace("&", "").replace("*", ""), begin.GetCharNum(), begin.GetLevel()); //los parametros quedan insertados en el principio del metodo, en orden inverso
node.SetNext(begin.GetNext());
begin.SetNext(node);
tempStr = tempStr.trim();
String TipoDato;
int beg = 0;
int CantAmpersands = 0;
while (beg < tempStr.length() - 1 && PERMITIDOS.indexOf(tempStr.charAt(beg)) > -1) {
beg++;
}
TipoDato = tempStr.substring(0, beg);
tempStr = tempStr.substring(beg, tempStr.length());
beg = 0;
int end = 1;
while (beg < tempStr.length() - 1 && (tempStr.charAt(beg) == ' ' || tempStr.charAt(beg) == '&')) {
if (tempStr.charAt(beg) == '&') {
CantAmpersands++;
}
beg++;
}
if (CantAmpersands > 1) {
throw new LanguageException(begin.GetCharNum(), begin.GetText(),
"A declaração dos parâmetros tiene extra símbolos do Ampersand (&)",
"Fique só com un símbolo de Ampersand (&)");
}
if (tempStr.indexOf("[") > -1) {
tempStr = tempStr.substring(0, tempStr.indexOf("["));
}
TipoDeParametro tipoParam = new TipoDeParametro();
tipoParam.Name = tempStr.substring(beg, tempStr.length()).trim();
tipoParam.PorValor = CantAmpersands == 0;
tipoParam.Tipo = TipoDato;
rutina.parametrosDefinition.add(tipoParam);
}
}
}