package Portugol.Language.Analisador;
import static Portugol.Language.Analisador.Simbolo.REGISTO;
import Portugol.Language.Calcular.Calculador;
import Portugol.Language.Utilitario.IteratorArray;
import Portugol.Language.Utilitario.LanguageException;
import Portugol.Language.Utilitario.Values;
import java.util.Vector;
import javax.swing.Icon;
public class SymbolArray extends Simbolo {
public static String VERSION = "Versão:2.0 \t(c)Augusto Bilabila e David Silva Barrera";
static public Icon SymbolArrayIcon;
/**
* Creates a new instance of Array
*/
public Vector<Simbolo> dataValues = new Vector<Simbolo>();
public String IndiceOrigen;//David:
Vector<Integer> indexHeights = new Vector<Integer>();
Vector<Integer> indexLimits = new Vector<Integer>();
// index corrent
int currentIndex = -1;
private int numElements = 1;
static public String ErroForaLimites = "FORA DOS LIMITES";
// definition tem os indexes e os valores
public SymbolArray(String modify, String type, String name, Vector<Integer> indLims, Vector<Simbolo> values, int level, Vector memory, String origTxt)
throws LanguageException {
TextoOrigen = origTxt;
if (modify.equalsIgnoreCase(Keyword.GetTextKey(Keyword.CONSTANTE))) {
this.isConst = true;
} else {
this.isConst = false;
}
this.type = getType(type);
typeLexema = type;
this.name = name.trim();
this.value = Values.getDefault(typeLexema);
this.level = level;
IndiceOrigen = ""; //David: Se inicializa mas tarde, en el metodo de abaixo
MakeArray(indLims);
PutValues(values);
}
public SymbolArray(SymbolArray origen) throws LanguageException {
TextoOrigen = origen.TextoOrigen;
isConst = origen.isConst;
type = origen.type;
typeLexema = origen.typeLexema;
IndiceOrigen = origen.IndiceOrigen;
name = origen.name.trim();
value = origen.value;
this.level = level;
MakeArray(origen.indexLimits);
PutValues(origen.dataValues);
}
public void copyFrom(SymbolArray arreglo) throws LanguageException {
if (!this.TextoOrigen.equals(arreglo.TextoOrigen)) {
throw new LanguageException("Os vectores não são equivalentes", "Mude a declaração, no parâmetro de chamada");//David:Revisar
}
dataValues.clear();
for (int i = 0; i < arreglo.dataValues.size(); i++) {
if (arreglo.dataValues.get(i) instanceof SymbolArray) {
dataValues.add(new SymbolArray((SymbolArray) arreglo.dataValues.get(i)));
} else if (arreglo.dataValues.get(i) instanceof SymbolComposto) {
dataValues.add(new SymbolComposto((SymbolComposto) arreglo.dataValues.get(i)));
} else if (arreglo.dataValues.get(i) instanceof SymbolObjeto) {
dataValues.add(new SymbolObjeto((SymbolObjeto) arreglo.dataValues.get(i)));
} else //if (arreglo.dataValues.get(i) instanceof Simbolo)
{
dataValues.add(new Simbolo(arreglo.dataValues.get(i)));
}
}
}
public void copyFrom(SimboloDeParametro origen) throws LanguageException {
if (origen == null) {
return;
}
if (origen.Value instanceof SymbolArray) {
SymbolArray arreglo = (SymbolArray) origen.Value;
this.copyFrom(arreglo);
} else {
throw new LanguageException("Tipo de parâmetro não é equivalente ao esperado", "Mude o tipo de parâmetro na chamada");//David:Revisar
}
}
//coloca o current index na posicao pretendida
public void SetIndex(String varName, Vector memory) throws LanguageException {
IteratorArray iter = new IteratorArray(varName);
String nome = iter.getNext();
while (iter.hasMoreElements()) {
nome += "[";
String index = iter.getNext();
Object value = Expressao.Evaluate(index, memory);
if (value instanceof String) {
nome += Integer.parseInt((String) value) + "]";
} else if (value instanceof Simbolo) {
if (!((Simbolo) value).isNumber()) {
throw new LanguageException("O símbolo " + varName + " tem de ser um número",
" Tente alterar o símbolo para um tipo numérico");
}
nome += ((Integer) ((Simbolo) value).getValue()).toString() + "]";
} else {
nome += "0" + "]";
}
}
try {
this.currentIndex = this.getFlatIndex(nome);
} catch (Exception e) {
//this.currentIndex = -1;
throw new LanguageException(
e.getMessage(),
" Tente alterar o símbolo para número");
}
}
//-----------------------------------------------------------------------
public void setValue(Object val) throws LanguageException {
if (this.isConst) {
throw new LanguageException("O símbolo " + this.name + " é uma constante, por isso, não pode receber valor",
" Altere o símbolo para variável normal");
}
Simbolo v = getNormalizedValue((String) val);
v.setName(new Integer(currentIndex).toString());
dataValues.set(currentIndex, v);
}
/**
* retorna o valor
*
* @return valor
*/
@Override
public Simbolo getValue() {
return dataValues.get(currentIndex);
}
private void MakeArray(Vector<Integer> indLims) {
numElements = 1;
for (int i = 0; i < indLims.size(); i++) {
int number = indLims.get(i);
indexLimits.add(number);
indexHeights.add(0);
numElements *= number;
IndiceOrigen = IndiceOrigen + "[" + Integer.toString(number) + "]";
}
// peso de cada indice no array
// necessario para os tornar linear [2][3] => 12
int height = 1;
for (int i = indexLimits.size() - 1; i >= 0; i--) {
indexHeights.set(i, height);
height *= Integer.parseInt(indexLimits.get(i).toString());
}
}
//////////////////////////////////////////////////////////////////////////////
private void PutValues(Vector<Simbolo> values) throws LanguageException {
int index = 0;
for (int i = 0; i < values.size(); i++) {
Object value = values.get(i);
if ((type == Simbolo.REGISTO || type == Simbolo.CLASSE) && value instanceof String && typeLexema.equals((String) value)) {
break;//David:
}
if (value instanceof SymbolComposto) {
dataValues.add((SymbolComposto) value);
} else if (value instanceof SymbolObjeto) {
dataValues.add((SymbolObjeto) value);
} else if (value instanceof Simbolo) {
dataValues.add((Simbolo) value);
} else if (value instanceof SymbolArray) {
//David: Isto nao pode acontecer
} else {
dataValues.add(getNormalizedValue((String) value));
}
dataValues.get(index).setName(new Integer(index).toString());
index++;
}
Object defValue = Values.getDefault(typeLexema);
for (int i = index; i < numElements; i++) {
if (type == REGISTO) {
dataValues.add(new SymbolComposto("", typeLexema + " ", " nao_nome", typeLexema + "", level, (typeLexema + " nao_nome <- " + typeLexema)));
} else if (type == CLASSE) {
dataValues.add(new SymbolObjeto("", typeLexema + " ", " nao_nome", typeLexema + "", level, (typeLexema + " nao_nome <- " + typeLexema)));
} else {
dataValues.add(new Simbolo("", typeLexema + " ", " nao_nome", defValue, level, (typeLexema + " nao_nome")));
}
dataValues.get(i).setName(new Integer(i).toString());
}
}
//////////////////////////////////////////////////////////////////////////////
/**
* retorna o valor
*
* @return valor
*/
public String getValue(String var) {
try {
int index = getFlatIndex(var);
return dataValues.get(index).toString();
} catch (Exception e) {
return e.getMessage();
}
}
/**
* retorna o valor
*
* @return valor
*/
public String getFlatValue(int index) {
if (index >= 0 && index < this.numElements) {
return dataValues.get(index).toString();
} else {
return "ERRO";
}
}
//////////////////////////////////////////////////////////////////////////////
/**
* retorna o valor
*/
public void setValue(String var, String value) throws Exception {
// introduzir o value em this
// causa excepcoes se houver erro em value e normaliza o valor
Simbolo v = getNormalizedValue(value);//David: Aqui pode ficar asi direito
int index = getFlatIndex(var);
v.setName(new Integer(index).toString());
dataValues.set(index, v); //David: Aqui pode ficar asi direito
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
private int getFlatIndex(String var) throws Exception {
int index = 0;
IteratorArray iter = new IteratorArray(var.trim());
String nameVar = iter.getNext().trim();
if (!nameVar.equalsIgnoreCase(name)) {
throw new Exception("ERRO NO NOME da VARIAVEL");
}
int numIndex = 0;
while (iter.hasMoreElements()) {
String exp = iter.getNext();
Object result = Calculador.CalulateValue(Expressao.ExpresionStringToVector(exp));
int number = Integer.parseInt((String) result);
if (number < 0) {
throw new Exception("ERRO NO INDECE " + exp);
}
if (number >= Integer.parseInt(indexLimits.get(numIndex).toString())) {
throw new Exception(ErroForaLimites + ": " + exp);
}
if (numIndex > indexLimits.size()) {
throw new Exception("ERRO NO INDECE :" + exp + " - NAO DEFENIDO");
}
index += number * Integer.parseInt(indexHeights.get(numIndex).toString());
numIndex++;
}
return index;
}
/**
* verifica se uma expressao is um array
*
* @param name expressao
* @return array[] ?
*/
public static boolean isArray(String name) {
int c1 = name.indexOf('[');
int c2 = name.indexOf(']');
return c1 * c2 > 0 && c2 > c1;
}
public String toString() {
return name + " = " + dataValues.toString();
}
public Vector getDimensions() {
// fazer uma copia
// para evitar ser alterado
return indexLimits;
}
public int getNumElements() {
return numElements;
}
/**
* nome =
*
* @param var varivel a comparar
* @return nome = paramentro
*/
public boolean nameEqual(String var) {
int p = var.indexOf('[');
if (p > 0) {
return name.equalsIgnoreCase(var.substring(0, p).trim());
} else {
return var.equalsIgnoreCase(name);
}
}
public static void main(String args[]) {
System.out.println("ARRAYS");
Vector memory = new Vector();
try {
// memory.add(new Simbolo("variavel", "inteiro", "numero1", "10", 0));
// memory.add(new Simbolo("variavel", "inteiro", "numero2", "20", 0));
// memory.add(new Simbolo("variavel", "inteiro", "numero3", "30", 0));
// SymbolArray a = new SymbolArray("variavel", "real", "vetor", "[2][2][2]", " { 1+3 ,2,3,4,5,6,7,8} ", 1, memory);
//System.out.println("Nome\t:" + a.getName());
//String var ="vetor[1][1][1]";
//System.out.println(a.toString());
//a.setValue(var,"20.0");
String var = "vetor[numero1/10][0][numero3/numero1 - 2]";
// a.SetIndex(var, memory);
//a.setValue("10");
// System.out.println(" Var = " + a.getValue());
//a.setValue(var,"10");
// System.out.println(a.toString());
//System.out.println(var + " = " + a.getValue(var));
} catch (Exception e) {
System.out.println(e.toString());
}
}
public boolean typeEqual(Simbolo otro) {
if (otro instanceof SymbolArray) {
return (typeLexema + " " + IndiceOrigen).equals((((SymbolArray) otro).typeLexema + " " + ((SymbolArray) otro).IndiceOrigen));
} else {
return false;
}
}
public Icon getIcon() {
return SymbolArrayIcon;
}
}