package Portugol.Language.Analisador;
import Portugol.Language.Calcular.Calculador;
import Portugol.Language.Criar.Intermediario;
import Portugol.Language.Criar.NodeInstruction;
import Portugol.Language.Criar.SubrutinePlayer;
import Portugol.Language.Utilitario.IteratorArray;
import Portugol.Language.Utilitario.IteratorCodeParams;
import Portugol.Language.Utilitario.IteratorString;
import Portugol.Language.Utilitario.LanguageException;
import Portugol.Language.Utilitario.Values;
import java.util.Vector;
/**
* @author Augusto Bilabila(2011) Original de Antonio manso(2006)
*/
public class Variavel {
public static String VERSION = "Versão:2.0 \t(c)Augusto Bilabila e David Silva Barrera";
private static String caracteres_aceites = "abcdefghijklmnopqrstuvxywz"
+ "ABCDEFGHIJKLMNOPQRSTUVXYWZ"
+ "._0123456789";
public static boolean isNameAcceptable(String nameVar) {
String name = nameVar.trim(); //David: Aqui deberia revolverse otro valor, de modo que el chamador pueda saber cual es el error especifico y dar una mejor propuesta de solucion
if (name.length() == 0) {
return false;
}
if (Character.isDigit(name.charAt(0))) {
return false;
}
for (int i = 1; i < name.length(); i++) {
if (caracteres_aceites.indexOf(name.charAt(i)) == -1) {
return false;
}
}
if (Keyword.IsKeyword(nameVar) || Calculador.IsCalculus(nameVar)) {
return false;
}
return true;
}
/**
* calcula o erro do nome da variavel
*
* @param nameVar nome da variavel
* @return causa do erro
*/
public static String getErrorName(String nameVar) {
String name = nameVar.trim();
if (name.length() == 0) {
return " O nome não pode ser vazio ";
}
if (Character.isDigit(name.charAt(0))) {
return " O nome de uma variável não pode começar com um número ";
}
if (Keyword.IsKeyword(nameVar)) {
return name + ", Não pode ser o nome de uma variável, porque é uma palavra reservada! ";
}
if (Calculador.IsCalculus(nameVar)) {
return name + " É um elemento de cálculo ";
}
if (name.indexOf("=") != -1) {
return "O sinal \"=\" deve ser substituído por \"<-\" (sinal de subtração do pseudocódigo) ";
}
for (int i = 1; i < name.length(); i++) {
if (caracteres_aceites.indexOf("" + name.charAt(i)) == -1) {
return name + " Contém o carecter \"" + name.charAt(i) + "\" não é válido";
}
}
return "Erro no nome";
}
// PARA REGISTO
public static String getErrorNameRegisto(String nameVar) {
String nome = nameVar.trim();
if (nome.length() == 0) {
return " O nome não pode estar vazio ";
}
if (Character.isDigit(nome.charAt(0))) {
return " O nome de um registo não pode começar com um número ";
}
if (Keyword.IsKeyword(nameVar)) {
return nome + ", Não pode ser o nome de um REGISTO, porque é uma palavra reservada! Tenta dar um outro nome ";
}
if (Calculador.IsCalculus(nameVar)) {
return nome + " É um elemento de cálculo ";
}
for (int i = 1; i < nome.length(); i++) {
if (caracteres_aceites.indexOf("" + nome.charAt(i)) == -1) {
return nome + " Contém o carecter \"" + nome.charAt(i) + "\" não é válido ";
}
}
return "Erro no nome";
}
public static ParteDeExpresion getVariable(Object elemento, Vector searchMemory) throws LanguageException {
String name = "";
if (elemento instanceof String) {
name = (String) elemento;
Operador res = Operador.TryOperador(name);
if (res != null) {
return res;
}
return getVariable(name, searchMemory, searchMemory);
}
if (elemento instanceof Vector) {
Vector chmd = (Vector) elemento;
name = (String) chmd.get(0);
if (!(((String) chmd.get(1)).equals("(") && ((String) chmd.get(chmd.size() - 1)).equals(")"))) {
//en caso de que el vector no sea de un llamado a metodo
return getVariable(name, searchMemory, searchMemory);
}
int posR = name.indexOf(".");
String source = "";
while (posR > -1) {
source = source + (source.isEmpty() ? "" : ".") + name.substring(0, posR).trim();
name = name.substring(posR + 1).trim();
posR = name.indexOf(".");
}
SymbolObjeto ObjetoDono = null;
if (!source.isEmpty()) {
ParteDeExpresion Source = getVariable(source, searchMemory, searchMemory);
if (Source instanceof SymbolObjeto) {
ObjetoDono = (SymbolObjeto) Source;
}
}
return SubrutinePlayer.Player.SearchAndExecuteSubrutine(ObjetoDono, name, chmd, searchMemory);
}
return null;
}
//-------------------------------------------------------------------------
private static ParteDeExpresion getVariable(String name, Vector searchMemory, Vector dataMemory) throws LanguageException {
// return null;
String varName;
String Campo;
int posR = name.indexOf(".");
int posA = -1;//name.indexOf("[");
if (posR == -1 && posA == -1) {
varName = name;
Campo = "";
} else //if (posR > -1 && posA == -1)
{
varName = name.substring(0, posR).trim();
Campo = name.substring(posR + 1).trim();
}
int pa = Campo.indexOf("(");
int pb = Campo.indexOf(")");
//String varName = name.trim();
for (int index = searchMemory.size() - 1; index >= 0; index--) {
Simbolo v = (Simbolo) searchMemory.get(index);
if (v.nameEqual(varName)) {
if (posR == -1 && Campo.isEmpty()) {
if (v instanceof SymbolArray) {
if (varName.contains("[") && varName.contains("]")) {
((SymbolArray) v).SetIndex(varName, dataMemory);
return ((SymbolArray) v).getValue();
} else {
return v;
}
} else {
return v;
}
} else {
if (v instanceof SymbolArray) {
((SymbolArray) v).SetIndex(varName, dataMemory);
if (v.getValue() instanceof SymbolComposto) {
return getVariable(Campo, ((SymbolComposto) v.getValue()).Campos, dataMemory);
} else if (v.getValue() instanceof SymbolObjeto) {
if (pa > -1 && pb > -1 && pa < pb) {
return getVariable(Campo, dataMemory/*, ((SymbolObjeto) v.getValue()).tipoClasseBase*/);
} else {
return getVariable(Campo, ((SymbolObjeto) v.getValue()).Campos, dataMemory);
}
} else {
throw new LanguageException(
"Posiblemente este llamando a un metodo de un objeto dentro de un vector",
"Todavia no es permitido");
}
} else {
if (v instanceof SymbolComposto) {
return getVariable(Campo, ((SymbolComposto) v).Campos, dataMemory);
}
if (v instanceof SymbolObjeto) {
if (Intermediario.console != null //não é expandir senao executar
&& ((SymbolObjeto) v).Inicializado == false) {
throw new LanguageException(
"Não pode utilizar o objeto \" " + ((SymbolObjeto) v).getName() + " \" antes de ser inicializado com o Construtor ", //David: revisar ortografia
"Antes utilice um código similar ao seguinte: \"" + ((SymbolObjeto) v).getName() + " <- NOVO " + ((SymbolObjeto) v).tipoClasseBase.Name.toLowerCase() + "( . . . )\"");
}
if (pa > -1 && pb > -1 && pa < pb) {
return getVariable(Campo, dataMemory/*, ((SymbolObjeto) v).Campos*/);
} else {
return getVariable(Campo, ((SymbolObjeto) v).Campos, dataMemory);
}
} else {
throw new LanguageException(
"Posiblemente esté llamando a un método de un objeto",
"Todavia no es permitido");
}
}
}
}
}
return null;
}
public static void defineVAR(NodeInstruction node, Vector memory, Vector<TipoDeParametro> params, Vector<SimboloDeParametro> paramVals) throws LanguageException {
if (SymbolArray.isArray(node.GetText())) {
Variavel.defineArray(node, memory, params, paramVals);
} else {
Variavel.defineSimples(node, memory, params, paramVals);
}
}
//------------------------------------------------------------------------
public static void defineSimples(NodeInstruction node, Vector memory, Vector<TipoDeParametro> params, Vector<SimboloDeParametro> paramVals) throws LanguageException {
// VARIAVEL TIPO VAR <- VALOR
IteratorString tok = new IteratorString(node.GetText());
String modif = tok.current();
tok.next();
String tipo = tok.current();
tok.next();
String nome = tok.current();
tok.next();
String atribui = tok.current();//<-
tok.next();
String valorUnproc = tok.getUnprocessedString();
Object valor = null;
SimboloDeParametro Parametro = null;
Simbolo v = null;
try {
int pos = -1;
for (int i = 0; i < params.size(); i++) {
if (params.get(i).Name.toUpperCase().equals(nome.toUpperCase())) {
pos = i;
break;
}
}
if (pos > -1) {
valor = null;
Parametro = paramVals.get(pos);
} else {
if (node.EsReferencia && SubrutinePlayer.Player.instanciaSubrutineActual != null && SubrutinePlayer.Player.instanciaSubrutineActual.InstanciaDono != null) {
for (int kk = 0; kk < SubrutinePlayer.Player.instanciaSubrutineActual.InstanciaDono.Campos.size(); kk++) {
if (SubrutinePlayer.Player.instanciaSubrutineActual.InstanciaDono.Campos.get(kk).nameEqual(nome)) {
v = SubrutinePlayer.Player.instanciaSubrutineActual.InstanciaDono.Campos.get(kk);
break;
}
}
} else {
valor = Expressao.Evaluate(valorUnproc, memory);
}
}
} catch (Exception e) {
throw new LanguageException(
node.GetCharNum(), node.GetText(),
e.toString(),
"Verifique a expressão <" + valorUnproc + ">");
}
if (v == null) {
if (Simbolo.getType(tipo) == Simbolo.REGISTO) {
v = new SymbolComposto(modif, tipo, nome, valor, node.GetLevel(), node.GetText());
} else if (Simbolo.getType(tipo) == Simbolo.CLASSE) {
v = new SymbolObjeto(modif, tipo, nome, valor, node.GetLevel(), node.GetText());
} else {
v = new Simbolo(modif, tipo, nome, valor, node.GetLevel(), node.GetText());
}
v.copyFrom(Parametro);
}
memory.add(v);
}
//=========================================================================
public static void defineArray(NodeInstruction node, Vector memory, Vector<TipoDeParametro> params, Vector<SimboloDeParametro> paramVals) throws LanguageException {
// VARIAVEL TIPO VAR <- VALOR
IteratorString tok = new IteratorString(node.GetText());
String modif = tok.current();
tok.next();
String type = tok.current();
tok.next();
String name = tok.current();
tok.next();
String rest = tok.getUnprocessedString();
int atr = rest.indexOf(Keyword.ATRIBUI);
String indexes = rest.substring(0, atr).trim();
String valorUnProc = rest.substring(atr + Keyword.ATRIBUI.length()).trim();
Vector<Integer> indexLimits = new Vector<Integer>();
IteratorArray iter = new IteratorArray(indexes);
while (iter.hasMoreElements()) {
String exp = iter.getNext();
Object result;
try {
result = Expressao.Evaluate(exp, memory);
} catch (LanguageException ex) {
if (ex.line > 0 && !ex.codeLine.isEmpty()) {
throw ex;
}
throw new LanguageException(
node.GetCharNum(), node.GetText(),
"O índice \" + exp + \" não é uma expressão válida: " + ex.getMessage(),
"Defina uma expressão válida para o índice");
}
if (!Values.IsInteger(result)) {
throw new LanguageException(
node.GetCharNum(), node.GetText(),
exp + " = " + result + " não é uma expressão inteira",
"");
}
int number = Integer.parseInt((String) result);
if (number <= 0) {
throw new LanguageException(
node.GetCharNum(), node.GetText(),
exp + " = " + result + " não é um valor válido", "");
}
indexLimits.add(number);
}
SimboloDeParametro Parametro = null;
IteratorCodeParams itercp;
Vector<Simbolo> dataValues = new Vector<Simbolo>();
ParteDeExpresion pdexpr;
int pos = -1;
for (int i = 0; i < params.size(); i++) {
if (params.get(i).Name.toUpperCase().equals(name.toUpperCase())) {
pos = i;
break;
}
}
SymbolArray v = null;
if (pos > -1) {
Parametro = paramVals.get(pos);
if (Parametro.Value instanceof SymbolArray) {
v = new SymbolArray((SymbolArray) Parametro.Value);
} else {
throw new LanguageException(
"O tipo de dado não coincide",
"Coloque um vetor");
}
} else {
if (node.EsReferencia && SubrutinePlayer.Player.instanciaSubrutineActual != null && SubrutinePlayer.Player.instanciaSubrutineActual.InstanciaDono != null) {
for (int kk = 0; kk < SubrutinePlayer.Player.instanciaSubrutineActual.InstanciaDono.Campos.size(); kk++) {
if (SubrutinePlayer.Player.instanciaSubrutineActual.InstanciaDono.Campos.get(kk).nameEqual(name)) {
v = (SymbolArray) SubrutinePlayer.Player.instanciaSubrutineActual.InstanciaDono.Campos.get(kk);
break;
}
}
} else {
if (indexLimits.size() == 1) {
int index = 0;
itercp = new IteratorCodeParams(valorUnProc, ",{}");
while (itercp.hasMoreElements()) {
String value = itercp.current();
//Avaliar a expressao
// se nao for possivel avaliar provoca erro
Object result;
try {
pdexpr = Variavel.getVariable(value, memory);
// if (pdexpr == null) {
// throw new LanguageException(
// node.GetCharNum(), node.GetText(),
// "A EXPRESSÃO :" + value + " NÃO FOI RECONHECIDA",
// "MUDE A EXPRESSÃO <" + value + ">");
// }
///Hay que verificar que coincidan los tipos de VAR y el tipo base del arreglo
if (pdexpr instanceof Operador) {
//esto no debe pasar
throw new LanguageException(
node.GetCharNum(), node.GetText(),
"A expressão :" + value + " não pode ser um operador",
"mude a expressão <" + value + ">");
} else if (pdexpr instanceof SymbolComposto) {
if (pdexpr instanceof SymbolArray) {
//esto no debe pasar, a menos que SymbolArray esté heredando de SymbolComposto
result = new SymbolArray((SymbolArray) pdexpr);
} else if (pdexpr instanceof SymbolComposto) {
if (((SymbolComposto) pdexpr).typeLexema.toUpperCase().trim().equals(type.toUpperCase().trim())) {
result = new SymbolComposto((SymbolComposto) pdexpr);
} else {
throw new LanguageException(
node.GetCharNum(), node.GetText(),
"A expressão :" + value + " não é de tipo " + ((SymbolComposto) pdexpr).typeLexema,
"Mude esta expressão <" + value + ">");
}
} else if (pdexpr instanceof SymbolObjeto) {
if (((SymbolObjeto) pdexpr).typeLexema.toUpperCase().trim().equals(type.toUpperCase().trim())) {
result = new SymbolObjeto((SymbolObjeto) pdexpr);
} else {
throw new LanguageException(
node.GetCharNum(), node.GetText(),
"A expressão :" + value + " não é de tipo " + ((SymbolObjeto) pdexpr).typeLexema,
"Mude esta expressão <" + value + ">");
}
} else if (pdexpr instanceof Simbolo) {
if (((Simbolo) pdexpr).typeLexema.toUpperCase().trim().equals(type.toUpperCase().trim())) {
result = new Simbolo((Simbolo) pdexpr);
} else {
throw new LanguageException(
node.GetCharNum(), node.GetText(),
"Erro na expressão :" + value + " não é de tipo " + ((Simbolo) pdexpr).typeLexema,
"Analise bem a sua expressão <" + value + ">");
}
} else {
throw new LanguageException(
node.GetCharNum(), node.GetText(),
"Erro na expressão :" + value,
"Analise bem a sua expressão <" + value + ">");
}
} else {
result = Expressao.Evaluate(value, memory);
}
} catch (Exception e) {
throw new LanguageException(
node.GetCharNum(), node.GetText(),
"Erro na expressão :" + value,
"Analise bem a sua expressão <" + value + ">");
}
//verificar se o resultado da expressao e compativel com a variavel
if (!Simbolo.IsCompatible(type, result)) {
throw new LanguageException(
node.GetCharNum(), node.GetText(),
"O valor <" + result + "> não é permitido para variável " + type,
" Analise bem a sua expressão :" + value);
}
if (result instanceof Simbolo) //normalizar o resultado
{
dataValues.add((Simbolo) result);
} else if (result instanceof String) {
if (type.toUpperCase().equals(((String) result).toUpperCase())) {
//David: simbolo composto ou objeto?????
dataValues.add(new SymbolComposto("", type, "nao_nome", result, node.GetLevel(), (type + " nao_nome <-" + type)));
} else {
//David: Só simbolo
dataValues.add(new Simbolo("", type, "nao_nome", result, node.GetLevel(), (type + " nao_nome")));
}
}
index++;
if (index > indexLimits.get(0)) {
throw new LanguageException(
node.GetCharNum(), node.GetText(),
valorUnProc + " tem mais que " + indexLimits.size() + " elementos",
" Defina menos elementos");
}
itercp.next();
}
} else if (indexLimits.size() > 1 && !valorUnProc.equals("0")) {
throw new LanguageException(
node.GetCharNum(), node.GetText(),
"O CompAlg não suporta inicialização dos vetores com mais duma dimenção",
"Tire a inicialização.");
}
v = new SymbolArray(modif, type, name, indexLimits, dataValues, node.GetLevel(), memory, node.GetText());
v.copyFrom(Parametro);
}
}
memory.add(v);
}
//------------------------------------------------------------------------------
//-----------------------------------------------------------------------------
public static void replaceVariableValue(String varName, Object newValue, Vector memory) throws LanguageException {
ParteDeExpresion pde = Variavel.getVariable(varName.trim(), memory);
if (pde == null) {
throw new LanguageException(0, varName, " A variável \"" + varName + "\" NÃO ESTÁ DEFINIDA ",
" Verifique o nome da variável");//David:Revisar
}
if (pde instanceof SymbolArray) {
if (varName.contains("[") && varName.contains("]")) {
((SymbolArray) pde).SetIndex(varName, memory);
} else if (newValue instanceof SymbolArray) {
((SymbolArray) pde).copyFrom((SymbolArray) newValue);
return; //debe parar aqui, ya a copia foi feita
} else {
throw new LanguageException(0, varName,
"O vetor " + varName + " só pode recever valores do tipo " + pde.TextoOrigen,
"Mude a declaração");//David:Revisar
}
}
if (pde instanceof SymbolComposto) {
if (newValue instanceof SymbolComposto) {
((SymbolComposto) pde).copyFrom((SymbolComposto) newValue);
return; //debe parar aqui, ya a copia foi feita
} else {
throw new LanguageException(0, varName,
"O registo " + varName + " só pode recever valores do tipo " + pde.TextoOrigen,
"Mude a declaração");//David:Revisar
}
}
if (pde instanceof SymbolObjeto) {
if (newValue instanceof SymbolObjeto) {
((SymbolObjeto) pde).copyFrom((SymbolObjeto) newValue);
return; //debe parar aqui, ya a copia foi feita
} else {
throw new LanguageException(0, varName,
"O objeto " + varName + " só pode recever valores do tipo " + pde.TextoOrigen,
"Mude a assinação");//David:Revisar
}
}
((Simbolo) pde).setValue(newValue);
}
}