package Portugol.Language.Analisador; import Portugol.Language.Utilitario.LanguageException; import Portugol.Language.Utilitario.Values; import javax.swing.Icon; import javax.swing.JOptionPane; public class Simbolo extends ParteDeExpresion { public static String VERSION = "Versão:2.0 \t(c)Augusto Bilabila e David Silva Barrera"; static public Icon SimboloIcon; /** * tipo Vazio */ public final static int VAZIO = 0; /** * tipo Logico */ public final static int LOGICO = 1; /** * tipo Real */ public final static int REAL = 2; /** * tipo Inteiro */ public final static int INTEIRO = 3; /** * tipo caracter (simbolo da tabela ASCII ) */ public final static int CARACTER = 4; /** * tipo Texto (strings) */ public final static int TEXTO = 5; /** * tipo Registo (registers) */ public final static int REGISTO = 6; /** * tipo Classe */ public final static int CLASSE = 7; /** * tipo Desconhecido */ public final static int DESCONHECIDO = -1; /** * se is constante ou variavel */ protected boolean isConst; /** * tipo de dados */ protected int type; public String typeLexema;//David: Paa almacenar o nome real do tipo do dado //public String TextoOrigen; //David: vai ter a linha origen da declaração /** * nome do simbolo */ protected String name; /** * valor */ protected Object value; /** * nivel do simbolo */ protected int level; public Simbolo(String modify, String type, String name, Object value, int level, 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;//parametro this.name = name.trim(); if (value == null) { setValue(Values.getDefault(typeLexema)); } else { //setValue(getNormalizedValue((String) value).getValue()); setValue(value); } this.level = level; } public Simbolo(Simbolo origen) throws LanguageException { TextoOrigen = origen.TextoOrigen; this.isConst = origen.isConst; this.type = origen.type; typeLexema = origen.typeLexema; this.name = origen.name.trim(); setValue(origen.getValue()); this.level = origen.level; } public Simbolo() { // somente para as classes derivadas (ex. array) //Muy mala practica, pero se queda asi por ahora } public void copyFrom(SimboloDeParametro origen) throws LanguageException { if (origen == null) { return; } if (origen.PorValor) { setValue(origen.Value); } else if (origen.Value instanceof Simbolo) { setValue(((Simbolo) origen.Value).value); } else { throw new LanguageException("Tipo de parâmetro não é equivalente ao esperado", "Mude o tipo de parâmetro na chamada");//David:Revisar } } public boolean IsCompatible(int type) { if (this.type == type) { return true; } if (this.type == Simbolo.REAL && type == Simbolo.INTEIRO) { return true; } if (this.type == Simbolo.TEXTO && type == Simbolo.CARACTER) { return true; } return false; } /** * tipo da variavel * * @param t texto com o tipo * @return tipo */ public static int getType(String t) { t = t.toUpperCase().trim(); if (t.equalsIgnoreCase(Keyword.GetTextKey(Keyword.LOGICO))) { return LOGICO; } if (t.equalsIgnoreCase(Keyword.GetTextKey(Keyword.TEXTO))) { return TEXTO; } if (t.equalsIgnoreCase(Keyword.GetTextKey(Keyword.INTEIRO))) { return INTEIRO; } if (t.equalsIgnoreCase(Keyword.GetTextKey(Keyword.REAL))) { return REAL; } if (t.equalsIgnoreCase(Keyword.GetTextKey(Keyword.CARACTER))) { return CARACTER; } if (Keyword.DefineRegisto(t)) { return REGISTO; } if (Keyword.DefineClasse(t)) { return CLASSE; } return DESCONHECIDO; } public void setType(int tipo) { this.type = tipo; } public void setLevel(int l) { level = l; } //------------------------------------------------------------------------ public boolean isLogico() { if (type == LOGICO) { return true; } return false; } //------------------------------------------------------------------------ public boolean isNumber() { if (type == REAL) { return true; } if (type == INTEIRO) { return true; } return false; } //----------------------------------------------------------------------- public boolean isString() { if (type == TEXTO) { return true; } if (type == CARACTER) { return true; } return false; } //------------------------------------------------------------------------ public void setValue(Object val) throws LanguageException { if (this.isConst) { throw new LanguageException("Este símbolo " + this.name + " é uma constante, não pode receber valores", " Tente alterar o símbolo"); } if (val instanceof String && type != TEXTO && type != CARACTER && type != LOGICO) { value = getNormalizedValue((String) val).getValue(); //David: aqui debe ficar mesmo asi } else if (val instanceof String) { value = val; } else if (val instanceof Simbolo) { if (((Simbolo) val).getValue() instanceof String) { value = (String) ((Simbolo) val).getValue(); } else if (((Simbolo) val).getValue() instanceof Integer) { value = new Integer((Integer) ((Simbolo) val).getValue()); } else if (((Simbolo) val).getValue() instanceof Double) { value = new Double((Double) ((Simbolo) val).getValue()); } else if (((Simbolo) val).getValue() instanceof Boolean) { value = (Boolean) ((Simbolo) val).getValue(); } else { value = ((Simbolo) val).getValue(); } } else { value = val; } } protected Simbolo getNormalizedValue(String val) throws LanguageException { val = val.trim(); if (type == TEXTO) { if (val.length() < 2 || !Values.IsString(val)) { throw new LanguageException( 0, "", name + " é uma variável do tipo LITERAL/STRING", "\"" + val + "\" não é um texto"); } return new Simbolo("", typeLexema, "", new String(val), 0, (typeLexema + " nao_nome")); } else if (type == CARACTER) { if (!Values.IsString(val) || val.length() != 3) { throw new LanguageException( 0, "", name + " é uma variável do tipo CARACTER", "\"" + val + "\" não é um caracter"); } return new Simbolo("", typeLexema, "", new String(val), 0, (typeLexema + " nao_nome")); } else if (type == LOGICO) { if (!Values.IsBoolean(val)) { throw new LanguageException( 0, "", name + " é uma variável do tipo LOGICO", "\"" + val + "\" não é um valor lógico válido"); } return new Simbolo("", typeLexema, "", new String(val.toUpperCase()), 0, (typeLexema + " nao_nome")); } else if (type == REAL) { if (!Values.IsNumber(val)) { throw new LanguageException( 0, "", name + " é uma variável do tipo REAL", "\"" + val + "\" não é um valor real válido"); } double d = Values.StringToDouble(val); return new Simbolo("", typeLexema, "", new Double(d), 0, (typeLexema + " nao_nome")); } else if (type == INTEIRO) { if (!Values.IsValue(val)) { throw new LanguageException( 0, "", name + " é uma variável do tipo INTEIRO", "\"" + val + "\" não é um valor inteiro válido"); } int i = Values.StringToInteger(val); return new Simbolo("", typeLexema, "", new Integer(i), 0, (typeLexema + " nao_nome")); } else if (type == REGISTO) { if (!Values.IsRegisto(val)) { throw new LanguageException( 0, "", name + " é uma variável do tipo REGISTO", "\"" + val + "\" não é um registo válido"); } return new SymbolComposto("", typeLexema, "", typeLexema, 0, (typeLexema + " nao_nome")); } else if (type == CLASSE) { if (!Values.IsRegisto(val)) { throw new LanguageException( 0, "", name + " é uma variável do tipo CLASSE", "\"" + val + "\" não é uma classe válida"); } return new SymbolObjeto("", typeLexema, "", typeLexema, 0, (typeLexema + " nao_nome")); } return null; } /** * retorna o valor * * @return valor */ public Object getValue() { return value; } public Object getDefaultValue() {//David: Não chamar desde construtor return Values.getDefault(typeLexema); } public String getTypeLexema() { return typeLexema; } /** * tipo da variavel * * @return tipo */ public int getType() { return type; } /** * gets nome * * @return nome */ public void setName(String s) { name = s; } public String getName() { return name; } /** * nivel * * @return nivel da varivel */ public int getLevel() { return level; } /** * verifica se is constante * * @return a constante */ public boolean isConstant() { return this.isConst; } /** * return object String * * @return informacao da variavel */ public String toString() { StringBuffer str = new StringBuffer(); if (isConstant()) { str.append("\tCONSTANTE\n"); } else { str.append("\tVARIAVEL\n"); } str.append("nome\t:" + getName() + "\n"); str.append("valor\t:" + getValue() + "\n"); str.append("tipo\t:" + getTypeLexema() + "\n"); str.append("nivel\t:" + getLevel() + "\n"); return str.toString(); } /** * nome = * * @param var varivel a comparar * @return nome = paramentro */ public boolean nameEqual(String var) { return var.equalsIgnoreCase(name); } /** * verifica se o valor e o tipo sao compativeis * * @param type1 type de dados * @param value valor * @return compatibilidade */ public static boolean IsCompatible(Object target, Object value) { if (target == null || value == null) { return false; } int typeNUM; if (target instanceof String) { typeNUM = Simbolo.getType((String) target); if (typeNUM == Simbolo.DESCONHECIDO) { return false; } } else if (target instanceof Simbolo) { if (value instanceof Simbolo && (((Simbolo) target).type == Simbolo.REAL || ((Simbolo) target).type == Simbolo.INTEIRO) && (((Simbolo) value).type == Simbolo.REAL || ((Simbolo) value).type == Simbolo.INTEIRO)) { return true; } if (value instanceof Simbolo && ((Simbolo) target).type != Simbolo.REGISTO && ((Simbolo) target).type != Simbolo.CLASSE && ((Simbolo) target).type == ((Simbolo) value).type) { return true; } if (value instanceof Simbolo && ((Simbolo) target).type == Simbolo.REGISTO && ((Simbolo) target).type == Simbolo.CLASSE && ((Simbolo) target).type == ((Simbolo) value).type && ((Simbolo) target).typeLexema.toUpperCase().equals(((Simbolo) value).typeLexema.toUpperCase())) { return true; } typeNUM = ((Simbolo) target).type; } else { return false; } if (typeNUM == Simbolo.REAL && Values.IsNumber(value)) { return true; } if (typeNUM == Simbolo.INTEIRO && Values.IsInteger(value)) { return true; } if (typeNUM == Simbolo.LOGICO && Values.IsBoolean(value)) { return true; } if (typeNUM == Simbolo.CARACTER && Values.IsCharacter(value)) { return true; } if (typeNUM == Simbolo.TEXTO && Values.IsString(value)) { return true; } if (typeNUM == Simbolo.REGISTO || typeNUM == Simbolo.CLASSE && value instanceof Simbolo && ((Simbolo) value).type == typeNUM && target instanceof Simbolo && ((Simbolo) value).typeLexema.toUpperCase().equals(((Simbolo) target).typeLexema.toUpperCase())) { return true; } if (typeNUM == Simbolo.REGISTO || typeNUM == Simbolo.CLASSE && value instanceof Simbolo && ((Simbolo) value).type == typeNUM && target instanceof String && ((Simbolo) value).typeLexema.toUpperCase().equals(((String) target).toUpperCase())) { return true; } //Esta entrada deberia desaparecer. Es para la inicializacion de variables, para tener un valor por defecto para cada registo (su mismo nombre) if ( (typeNUM == Simbolo.REGISTO || typeNUM == Simbolo.CLASSE) && value instanceof String && target instanceof String && ((String) value).toUpperCase().equals(((String) target).toUpperCase())) { return true; } if ( (typeNUM == Simbolo.REGISTO || typeNUM == Simbolo.CLASSE) && value instanceof String && target instanceof Simbolo && ((String) value).toUpperCase().equals(((Simbolo) value).typeLexema.toUpperCase())) { return true; } return false; } /** * igual * * @param other segundo argumento * @return sao iguais? */ public boolean equal(Simbolo other) { if (!nameEqual(other.name)) { return false; } return other.level == level; } public boolean typeEqual(Simbolo otro) { if (otro instanceof Simbolo) { return type == otro.type && typeLexema.equals(otro.typeLexema); } else { return false; } } public Icon getIcon(){ return SimboloIcon; } }