/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package ast; import API.Functions; import common.Instruction; import API.Types; import API.Variables; import static ast.Semantic.current; import common.Log; import java.util.ArrayList; import java.util.Stack; /** * * @author Eugenio */ public class Semantic extends Log { protected Stack escopoStack = new Stack<>(); protected AbstractSyntaxTree ast; protected static Node current; // protected HashMap errosTemplate = new HashMap<>(); // protected boolean temporalErro = false; public Semantic() { } public Semantic(AbstractSyntaxTree ast) { this.ast = ast; } /** * Percorre a AST em chama o metodo viSitNode que redireciona para o * tratamento de cada no * * @param as * @throws Exception */ public Semantic Execute() throws Exception { _analise(ast.root); return this; } /** * Parte aux do metodo analiSe. * * @param n * @return * @throws Exception */ protected void _analise(Node n) throws Exception { if (null == n) { return; } current = n; switch (current.Get("class")) { default: visitNode(); if (!n.childrens.isEmpty()) { for (Node n2 : n.childrens) { _analise(n2); } } } } protected void visitNode() throws Exception { switch (current.Get("class")) { case "type": CheckType(); break; case "selector": CheckSelector(); break; case "def.assign": CheckAssign(); break; case "call": CheckCall(); break; case "dec.const": break; case "dec.type": break; // case "_array": //// chkArray(); // break; // case "read": // chkRead(); // break; // case "print": // chkPrint(); // break; // case "dec::var": // verificarDecVariavel(); // break; // case "return": // checkRetornoFuncao(); // break; // case "var": // verificarVariavel(current); // break; // case "parametros::list": // testarListaParametros(); // break; // case "op::unaria": // chkOperacaoUnario(); // break; // case "expr::arithmetic": // exprArithmetic(); // break; // case "exp::boolena": // chkOperacaoBooleano(); // break; // case "dec::function": // case "main": // verificarFuncao(); // break; } } protected void CheckType() { String type = current.Get("type"); if (!Types.Primitive(type) && !Types.Defined(type)) { AddError(new Instruction() .Set("class", "Type") .Set("msg", String.format("Tipo '%s' não definido", type)) .Set("line", current.Get("line")) .Set("col", current.Get("col")) ); } } protected void CheckSelector() { try { String type; switch (current.Get("subclass")) { case "operand": if (!current.eq("classType", "value") && Variables.Get(current.getText()) == null) { throw new Exception("Variavel " + current.getText() + " não definida"); } break; case "selector": type = Variables.TypeOf(current.Get("value")); if (type.equals("undefined")) { throw new Exception("Variavel " + current.getText() + " não definida"); } // current.Set("type", type); // System.out.println("CheckSelector:" + current); break; case "index": // System.out.println("CheckSeletor:" + current); String varname = current.Get("value"); type = Variables.TypeOf(varname); if (type.equals("undefined")) { throw new Exception("Variavel " + current.getText() + " não definida"); } Node var = Variables.Get(varname); Node ical; ArrayList indexesCall = new ArrayList<>(current.childrens()); ArrayList indexesDecl = var.childrens(); if (indexesCall.size() > indexesDecl.size()) { // todo exibir os indices throw new Exception("Variavel " + current.getText() + " não aceita acesso indexado"); } else { int idecval, icallval; for (Node idec : indexesDecl) { if (indexesCall.isEmpty()) { throw new Exception("Variavel " + current.getText() + " não aceita acesso indexado"); } ical = indexesCall.remove(0); // se não for um indice numerico salta if (!ical.isNumber("value")) { continue; } icallval = ical.GetInt("value"); idecval = idec.GetInt("value"); if (idec.isNumber("value") && icallval >= idecval) { throw new Exception(String.format("Index ['%s'] fora do intervalo ['%s'] em %s", icallval, idecval, current.getText())); } } } break; } } catch (Exception e) { AddError(new Instruction() .Set("class", "Type") .Set("msg", e.getMessage()) .Set("line", current.Get("line")) .Set("col", current.Get("col")) ); } } protected void CheckAssign() throws Exception { ArrayList returns = new ArrayList<>(); Node f, funcret; for (Node attrib : current.childrens().get(1).childrens()) { switch (attrib.Class()) { case "call": f = Functions.Get(attrib.getText()); funcret = f.find("dec.return"); if (funcret != null) { for (Node r : funcret.childrens()) { returns.add(r.Get("type")); } } break; default: returns.add(attrib.Get("type")); break; } } ArrayList dsts = current.childrens().get(0).childrens(); if (dsts.size() != returns.size()) { throw new Exception(String.format("Atribuição incompativel. Esperando %d e atribuido %d", dsts.size(), returns.size())); } else { int i = 0; String attrib, typedst; for (Node dst : dsts) { attrib = returns.get(i++); // typedst = dst.Get("type"); typedst = typeoOf(dst); if (!typedst.equals(attrib)) { AddError(new Instruction() .Set("class", "Assing") .Set("msg", String.format("Tipo atribuição '%s' diferente do esperado '%s'", attrib, typedst)) .Set("line", current.Get("line")) .Set("col", current.Get("col")) ); } } // System.out.println("CheckAssign:" + returns); // A quantidade de retornos é igual a de destinos, verificar o tipo de cada atribuição } } protected String typeoOf(Node n) throws Exception { // System.out.println("TYPEOF:\n" + n.getText() + "\n[" + Variables.TypeOf(n.getText()) + "]"); if (n.eq("type", "")) { // Variables.type(n.getText(), n.Get("scope")); n.Set("type", Variables.TypeOf(n.getText())); } return n.Get("type"); } protected void CheckCall() throws Exception { // System.out.println("CheckCall:" + current); Node function = Functions.Get(current.getText()); // Verifica se a funcao foi definida if (function == null) { AddError(new Instruction() .Set("class", "Call") .Set("msg", String.format("A função '%s' não foi definida", current.getText())) .Set("line", current.Get("line")) .Set("col", current.Get("col")) ); return; } // Se a definicao contem argumentos verifica se na chamada possui o mesmo // numero de argumentos e se são do mesmo tipo ArrayList argumentsDelc = function.findAll("argument", "class"); ArrayList argsDelc = new ArrayList<>(); String type, pointer; Node t; for (Node args : argumentsDelc) { t = args.find("type"); type = t.Get("type"); pointer = t.Get("pointer"); for (int i = 0; i < args.find("ids").childrens().size(); i++) { argsDelc.add((pointer.equals("") ? "" : "&") + type); } } Node argumentsCall = current.find("arguments").find("exprs"); ArrayList argsCall = new ArrayList<>(); if (argumentsCall != null) { String prefix = ""; for (Node argCall : argumentsCall.childrens()) { // System.out.println("ArgCall:" + argCall); if (argCall.eq("subclass", "address") || argCall.eq("pointer", "*")) { prefix = "&"; } argsCall.add(prefix + argCall.Get("type")); } } int argsDeclCount = argsDelc.size(); int argsCallCount = argsCall.size(); if (argsCallCount != argsDeclCount) { AddError(new Instruction() .Set("class", "Call") .Set("msg", String.format("Chamada incompativel. Numero de parametros de chamada é '%s' e o esperado é '%s'", argsCallCount, argsDeclCount)) .Set("line", current.Get("line")) .Set("col", current.Get("col")) ); } else { // todo check types int i = 0; String callType; for (String declType : argsDelc) { callType = argsCall.get(i++); // System.out.println("Call arg:" + callType + ":" + declType); if (!declType.equals(callType)) { AddError(new Instruction() .Set("class", "Call") .Set("msg", String.format("Chamada incompativel. O parâmetro %s é do tipo '%s' e o esperado é '%s'", i, callType, declType)) .Set("line", current.Get("line")) .Set("col", current.Get("col")) ); } } } } } // /** // * Busca uma declaração de uma função, caso não exista adiciona erro ao Log // * // * @param nomeDaFuncao // * @param AddError // * @return Node | null // */ // protected static Node encontreFuncao(String id, boolean AddError) { // Node func = null; // if (id.substring(0, 2).equals("__")) { // // } else if (Functions.existe(id)) { // func = Functions.function(id); // } // if (func == null && AddError) { // AddError(Api.getFormatedPosition(current) // + "Chamada de função. Tentativa de chamar uma função {" // + id + "} não definida."); // } // return func; // } // // protected void chkOperacaoBooleano() { // Node n1 = getOperandoNaAst(current.getFilho(0), current); // Node n2 = getOperandoNaAst(current.getFilho(1), current); // // if (n1 == null || n2 == null) { // return; // } // // String esperado = ""; // String tipo1 = tipo(n1); // String tipo2 = tipo(n2); // // if (current.in("value", new String[]{"==", "!="})) { // if (!tipo1.equals(tipo2)) { // AddError(Api.getFormatedPosition(current) + " Comparação invalida. " // + "Comparação entre tipos diferentes. Param[1] do tipo {" + tipo1 + "} Param[2] do tipo {" + tipo2 + "}"); // } // } else { // if (current.in("value", new String[]{"<", ">", "<=", ">="})) { // esperado = "int"; // } else if (current.in("value", new String[]{"&&", "||"})) { // esperado = "bool"; // } // String op = current.getText(); // tipoCheck(n1, tipo1, esperado, op); // tipoCheck(n2, tipo2, esperado, op); // } // } // // /** // * Verifica:
// * -> Operação de atribuição. -> Se o endereço de destino é valido, seja // * variavel ou declarcao de uma -> Se o tipo atribuido corresponde com o // * esperado // * // * @throws Exception // */ // protected void chkAssign(Node current) throws Exception { // Node parent = current.parent; // // /** // * Se parent for igual assign::op entao deve se analisar a variavel, // * caso contrario sera dec::var e não precisa verificar o acesso a // * variavel // */ // Node var; // boolean isDeclaracao = true; // if (parent.igual("class", "assign::op")) { // isDeclaracao = false; // if (Constantes.existe(parent.getText())) { // _addViolacaoDeConstante(parent.getText()); // return; // } // var = parent.encontreByClass("var"); // _analise(var); // // } else { // var = parent; // } // // /** // * Apos verificar variavel, vamos verificar se o tipo atribuido é igual // * ao esperado; // */ // Node value = current.first(); // // /*Se valor for uma variavel e a mesma não existir*/ //// value.Set("verificador", "0"); // _analise(value); // /*Se ocorreu erro na verificação do valor atribuido*/ //// // String eTipo = parent.Get("tipo"), aTipo = tipo(value); // // if (var.igual("tipo", Types.REFERENCE)) { // if (isDeclaracao && value.diferente("acessoEndereco", "true")) { // AddError(Api.getFormatedPosition(value) + " Atribuição invalida. Reference ainda não aponta para uma área de memoria valida!"); // } // return; // } // // if (!aTipo.equals(eTipo)) { // AddError(Api.getFormatedPosition(value) + " Atribuição invalida. Tipo esperado {" // + eTipo + "} enquanto o atribuido foi {" + aTipo + "}."); // } // // } // // //--------------------------------------------------// // // // //##################################################// // /** // * Verifica:
// * -> Se uma variavel foi redeclara. // * // * @param nome // */ // protected boolean _$RedeclaracaoVar(String nome, Node current) throws Exception { // ArrayList declaracoes = current // .closest("atributos,dec::function,dec::thread,dec::globais,trap", "class") // .encontreTodos("dec::var", "class"); //// filtrarFilhosPorClass(); // int cId = current.GetInt("id"); // int tId; // for (Node node : declaracoes) { // tId = node.GetInt("id"); // if (tId >= cId) { // break; // } // if (node.igual("value", nome)) { // AddErrorWithPosition(" Redeclaração [ Variavel {" + nome // + "}]. Primeira definição na linha {" + node.Get("line") + "}"); // return true; // } // } // return false; // // } // // /** // * Verifica:
// * -> Redeclaração de uma função no mesmo escopo // * // * @throws Exception // */ // protected void _checkRedeclaracaoFuncao() throws Exception { // String nomeFuncao = current.getText(); // ArrayList funcoes = current.parent.filtrarFilhosPorClass("dec::function"); // int cId = current.GetInt("id"); // int tId; // for (Node node : funcoes) { // tId = node.GetInt("id"); // if (tId >= cId) { // break; // } // if (node.igual("value", nomeFuncao)) { // AddError(Api.getFormatedPosition(current) + "Redeclaração de função. Previa declaração na linha {" + node.Get("line") + "}"); // return; // } // } // } // // protected void _verificarAtribuicaoVetor(Node variavel, Node valor) throws Exception { //// System.out.println("Var:" + variavel.encontre("indices")); // // String tipoEsperado = variavel.Get("tipo"); // Node indices = variavel.encontre("indices"); // int numeroIndices = indices.getChildrenCount(); // //// System.out.println("\n\nAtribuicao:" + current); //// Node valor = current.getPrimeiroFilho(); //// System.out.println("valor:" + valor); // if (!valor.igual("class", "lista")) { // String tipo = valor.Get("tipo"); // AddErrorWithPosition("Atribuição invalida. Aguardando uma lista de " // + tipoEsperado + ". Um(a) {" + tipo + "} foi atribuido."); // return; // } //// System.out.println("Valor era matrix:" + valor.igual("matrix", "true")); // Node visit; // if (numeroIndices > 1 && !valor.igual("matrix", "true")) //Caso tenha mais de uma linha de inicializacao // { //// System.out.println("ATRIB:" + valor); // AddErrorWithPosition(" Numero de itens não corresponde ao esperado. Esperado {" + numeroIndices + "} atribuido {1}"); // return; // } // if (valor.igual("matrix", "true")) { // visit = valor; // } else { //Caso seja apenas um vetor //// valor:[value: lista, id: 17, _pos: 0, class: lista, tipo: array, line: 14, col: 16, file: program::exemplo, ][1,3,] sem () //// valor:[value: lista, id: 17, _pos: 0, class: lista, tipo: array, line: 14, col: 16, file: program::exemplo, ][lista,] () // //// valor:[value: lista, id: 8, _pos: 0, class: lista, tipo: array, line: 14, col: 14, file: program::exemplo, ][1,2,] //// valor:[value: lista, id: 8, _pos: 0, class: lista, tipo: array, line: 14, col: 14, file: program::exemplo, ][lista,] //// System.out.println("valor:" + valor); // Node lista = valor.first(); // if (lista.igual("class", "lista")) { // visit = lista; // } else { // visit = valor; // } // } // __conferirListaAtribuicao(indices, visit, 0, tipoEsperado, numeroIndices); // } // // protected void __conferirListaAtribuicao(Node indices, Node valor, int ind, String tipo, int numeroIndices) throws Exception { //// System.out.println("Valores:" + valor); // if (!indices.temFilho(ind)) { // return; // } // int numEle = indices.getFilho(ind).GetInt("value"); // int numAtrib = valor.getChildrenCount(); // // if (numeroIndices == 1) { //diz que e um vetor; // if (numEle != numAtrib) { // AddErrorWithPosition(" Numero de itens não corresponde ao esperado. Esperado {" // + numEle + "} atribuido {" + numAtrib + "}."); // } // checkTipo(tipo, valor.filhos(), ""); // } else { //diz que é uma matrix //// System.out.println("ASDASD:" + ind + ":" + (numeroIndices - 1)); // if (numEle != numAtrib) { // AddErrorWithPosition(" Numero de itens não corresponde ao esperado. Esperado {" // + numEle + "} atribuido {" + numAtrib + "}."); // return; // } // if (ind == numeroIndices - 1) { // checkTipo(tipo, valor.filhos(), ""); // } else { // for (Node atribuicao : valor.filhos()) { // __conferirListaAtribuicao(indices, atribuicao, ind + 1, tipo, numeroIndices); // } // } // } // } // // protected Node getOperandoNaAst(Node n, Node parent) { // if (n.eNumerico("value") || n.igual("class", "valor")) { // return n; // } // return findVariavel(n); // } // // /** // * // * @param n Sera extraido a poiscao e o texto // * @param tipo tipo do valor atribuido // * @param esperado tipo do valor esperado // * @param op operação [atribuição,] // */ // protected void tipoCheck(Node n, String tipo, String esperado, String op) { // if (tipo == null) { // tipo = "undefined"; // } // String acesso = (n.temAtributo("fullAccess")) ? n.Get("fullAccess") : n.getText(); // if (!tipo.equals(esperado)) { // AddError(Api.getFormatedPosition(n) + " Operação { " + op + " } espera um valor [" // + esperado + "]. Parametro { " + acesso + " } é do tipo [" + tipo + "]"); // } // } // // // protected static String tipoVar(Node n) { // Node nv = findVariavel(n); // String tipo = "undefined"; // /*Se a variavel não existir*/ // if (null == nv) { // return tipo; // } // // Node atributo = n.encontreByClass("atributo"); // // /*Se não tem atributo*/ // if (null == atributo) { // return n.Get("tipo"); // } // // /*Se tem atributo*/ // while (null != atributo) { // tipo = atributo.Get("tipo"); // atributo = atributo.encontreByClass("atributo"); // } // return tipo; // } // // protected static Node findVariavel(Node var) { // return findVariavel(var, true); // } // //// protected Node findVariavel(Node var, Node parent, boolean AddError) { // protected static Node findVariavel(Node var, boolean AddError) { //// if (Constantes.existe(var.getText())) { //// return Constantes. //// } // Node dec = Variables.find(var.getText(), var.Get("escopo")); // if (dec == null && AddError) { //// System.out.println("Var:" + var); //// new Exception().printStackTrace(); // AddError(Api.getFormatedPosition(var) + " Tentativa de acesso identificador {" + var.getText() + "} não declarada no escopo."); // } // return dec; // } // // // // /** // * // * @param n // * @param tipoEsperado // * @param onde // * @return true se iguais e false caso sejam diferentes // */ // protected boolean checkTipo(String tipoEsperado, Node n, String onde) { // if (n.igual("tipo", "undefined")) { // switch (n.Class()) { // case "var": // n = findVariavel(n); //// n = ast.encontreDeclaracao(n, n.parent); // break; // case "function::call": // n = encontreFuncao(n.getText(), true); //// n = ast.encontreFuncao(n.getText()); // break; // } // } // // if (!n.igual("tipo", tipoEsperado)) { // switch (onde) { // case "retorno": // AddErrorWithPosition(" Retorno invalido. Tipo esperado {" + tipoEsperado + "} enquanto o atribuido foi {" + n.Get("tipo") + "}."); // break; // default: // AddErrorWithPosition(" Atribuição invalida. Tipo esperado {" + tipoEsperado + "} enquanto o atribuido foi {" + n.Get("tipo") + "}."); // } // return false; // } // return true; // } // // protected void checkTipo(String tipoEsperado, ArrayList nodes, String onde) { // for (Node v : nodes) { // checkTipo(tipoEsperado, v, onde); // } // } // // public static boolean testExist(Node n) { // return testExist(n, true); // } // // public static boolean testExist(Node n, boolean AddError) { // if (n == null) { // return false; // } // switch (n.Get("class")) { //// case "function::call": //// Node func = encontreFuncao(n.getText(), AddError); //// if (func != null) { //// return true; //// } //// break; //// case "dec::var": //// return true; //// case "assign::op": //// n = n.first(); //// case "var": //// return findVariavel(n, AddError) != null; //// //// case "const": //// return Constantes.existe(n.getText()); //// //// case "op::unaria": //// case "exp::boolena": //// case "valor": //// case "exp::aritimetica": //// return true; // } // return false; // } // // protected Node program() { // return Root().encontre("program"); // } // // protected boolean _$redeclaracao(String nome, String tipo, String onde, int id) throws Exception { // for (Node c : program().encontre(onde).filhos()) { // if (nome.equals(c.getText()) && id > c.GetInt("id")) { // AddErrorWithPosition(" Redeclaração [ " + tipo + " {" + nome + "}]. Primeira definição na linha {" + c.Get("line") + "}"); // return true; // } // } // return false; // } // // /** // * Verifica:
// * -> Se a constante é duplicada existe;
// * -> Se o tipo atribuido é igual ao esperado // */ // protected void chkConstante() throws Exception { // /*Verificar se constante foi redeclarada*/ // //// if (_$redeclaracao(current.getText(), "Constante", "constantes", current.GetInt("id"))) { //// return; //// } // } //// // /** // * Verifica:
// * -> Se existe uma constante com mesmo nome
// * -> Se o tipo existe
// * -> Se ocorre redeclaração da variavel // * // * @throws Exception // */ // protected void verificarDecVariavel() throws Exception { // String nome = current.getText(); // if (_$RedeclaracaoVar(nome, current)) { // return; // } // if (Constantes.existe(nome)) { // AddErrorWithPosition(" Declaração invalida. Variavel {" + nome + "} com mesmo identificador de uma constante."); // return; // } // _testeTipoValido(current); // /*Se for matrix avalia os limites*/ // if (current.igual("matrix", "true") // && !_$indicesValidos(current, current.encontre("indices"), false)) { // } // Node assign = current.encontreByClass("assign"); // if (null != assign) { // chkAssign(assign); // } // } // // /** // * Verifica se o tipo existe; Adiciona mensagem de erro caso contrario; // * // * @param n // * @return // * @throws Exception // */ // protected boolean _testeTipoValido(Node n) throws Exception { // String tipo = n.Get("tipo"); // boolean exit = Types.existe(tipo); // if (!exit) { // AddError(Api.getFormatedPosition(n) + " Tipo invalido. Tipo {" + tipo + "} não definido."); // } // return exit; // } // // /** // * Verifica:
// * -> Função com mesmo nome de uma variavel
// * -> Se função foi redeclarada
// * // * @throws Exception // */ // protected void verificarFuncao() throws Exception { // // String nomeFuncao = current.getText(); // if (Variables.existe(current)) { // AddErrorWithPosition("Declaração invalida. Função com mesmo nome de uma variavel {" + nomeFuncao + "}."); // } // _$redeclaracao(nomeFuncao, "Funções", "funcoes", current.GetInt("id")); //// _checkRedeclaracaoFuncao(); // // _checkRetornoFuncao(); // } // // /** // * Verifica:
// * -> Se o retorno é o mesmo esperado pela função ; // */ // protected void checkRetornoFuncao() { // Node parent = current.closest("dec::function,dec::thread", "class"); // /*Se não estiver dentro de uma função ou thread*/ // if (null == parent) { // return; // } // /*Se estiver dentro de uma thread não verifica*/ // if (parent.igual("class", "dec::thread")) { // return; // } // String tipoEsperado = parent.Get("tipo"), // tipoAtribuido = tipo(current.first()); // // if (!tipoAtribuido.equals(tipoEsperado) && !tipoAtribuido.equals(Types.REFERENCE)) { // AddErrorWithPosition(" Tipo de retorno invalido. Retornando {" + tipoAtribuido + "} enquanto o esperador é {" + tipoEsperado + "}"); // } // } // // // /** // * Verifica:
// * -> Se função existe // */ // protected void chkChamadaDeFuncao() { // if (current.in("value", new String[]{"print", "read"})) { // return; // } // String id = current.getText(); // // if (null == encontreFuncao(id, false)) { // AddErrorWithPosition(" Chamada de função invalida. Não foi encontrada declaração para a função ['" + id + "']."); // } // } // // /** // * Verifica:
// * -> Se uma variavel existe.
// * -> Se for matrix avalia os limites // * // * @param nome // */ // protected void verificarVariavel(Node var) throws Exception { // Node dec = findVariavel(var, true); // if (null == dec) { // var.Set("verificador", "1"); // return; // } // if (!_$checkAtributoAndIndices(dec, var)) { // var.Set("verificador", "1"); // } // } // // /** // * Verifica:
// * -> Se uma atributo existe
// * -> Se for matrix avalia os limites // * // * @throws Exception // */ // protected boolean checkAtributo(Node current) throws Exception { // if (current == null) { // return false; // } // // String tipoParent = current.parent.Get("tipo"); // // if (tipoParent.equals("undefined")) { // return false; // } // // Node pTipo = Types.Get(tipoParent); // String atributo = Variables.clearName(current.getText()); // Node dec = pTipo.first().encontre(atributo); // /*Verifica se o atributo existe*/ // if (null == dec) { // AddErrorWithPosition(" Acesso invalido de atributo. A variavel [ " // + current.parent.getText() + " | tipo: " + pTipo.getText() // + " ] não possui o atributo {" + atributo + "}"); // return false; // } // return _$checkAtributoAndIndices(dec, current); // } // // /** // * Executa recursivamente a verificação de atributos e a verificação de // * indices // * // * @param dec // * @param current // * @throws Exception // */ // protected boolean _$checkAtributoAndIndices(Node dec, Node current) throws Exception { // /*Verificar array limites*/ // Node indices = current.encontre("indices"); // if (null != indices && !_$indicesValidos(dec, indices, true)) { // current.Set("verificador", "1"); // return false; // } // Node atributo = current.encontreByClass("atributo"); // /*Se tem um proxumo atributo e é array*/ // if (null != atributo && dec.igual("matrix", "true")) { // Node decInd = dec.encontre("indices"), // curInd = current.encontre("indices"); // // /*Isso indica que deve estar sendo accessado um array e uma variavel*/ // if (null == curInd || decInd.getChildrenCount() > curInd.getChildrenCount()) { // // AddErrorWithPosition(" Acesso invalido. Tentando acessar o atributo {" + atributo.getText() + "} de um array."); // current.Set("verificador", "1"); // return false; // } // } // // /*Ativa recursao dos atributos*/ // if (!checkAtributo(atributo)) { // current.Set("verificador", "1"); // return false; // } // return true; // } // // /** // * Verifica:
// * -> Se os indices são do tipo inteiro
// * -> Se for valor verifica se o limite é valido // * // * @param dec // * @param indicesAccess // * @param chkLimite // * @throws Exception // */ // protected boolean _$indicesValidos(Node dec, Node indicesAccess, boolean chkLimite) throws Exception { // boolean valid = true; // /*Caso o a variavel não seja um matriz*/ // if (!dec.igual("matrix", "true")) { // AddErrorWithPosition(" Acesso invalido. Propriedade {" + dec.getText() + "} não é um vetor."); // return false; // } // ArrayList indices = indicesAccess.filhos(); // ArrayList decIndices = dec.encontre("indices").filhos(); // // if (indices.size() > decIndices.size()) { // AddErrorWithPosition(" Acesso invalido. Tentando acessar indices fora do espaço da matriz."); // return false; // } // // Node decIndice; // String tIndice; // Node indice; // for (int i = 0, valIndAce, valIndDec; i < indices.size(); i++) { // indice = indices.Get(i); // tIndice = tipo(indice); // // _analise(indice); // // if (tIndice.equals("undefined")) { // valid = false; // continue; // } // // /*Verifica se o indice é inteiro */ // if (!tIndice.equals("int")) { // AddErrorWithPosition(" Indice erro. Indice [" + (i + 1) + "] deve ser inteiro, {" + tIndice + "} atribuido."); // valid = false; // continue; // } // /*Quando for uma declaração não deve conferir os limites, verificação // apenas deve ser feita quando se tratar de acesso a variavel*/ // // /*Verificar limite apenas quando for numero inteiro*/ // if (!chkLimite || !indice.in("class", new String[]{"valor", "indice"})) { // continue; // } // // decIndice = decIndices.Get(i); // if (!decIndice.in("class", new String[]{"valor", "indice"})) { // continue; // } // // /* Quantidade de indices da chamada */ // valIndAce = indice.GetInt("value"); // valIndDec = decIndice.GetInt("value"); // // if (valIndAce >= valIndDec) { // AddErrorWithPosition(" Indice erro. Indice [" + (i + 1) + "], valor maximo {" + (valIndDec - 1) + "}, atribuido {" + valIndAce + "}."); // valid = false; // } // } // return valid; // } // // /** // * Registra o erro caso a quantidade de parametros seja diferente da // * declarada // * // * @param numParametros // * @param sizedec // */ // protected boolean _$verificarQuantidadeParametros(int numParametros, int sizedec) { // if (numParametros > sizedec) { // AddErrorWithPosition(" Chamada invalida. Função chamada com mais " // + "parametros que o declarado. Esperando {" // + sizedec + "}, atribuidos {" + numParametros + "}"); // return false; // } else if (numParametros < sizedec) { // AddErrorWithPosition(" Chamada invalida. Função chamada com menos " // + "parametros que o declarado. Esperando {" // + sizedec + "}, atribuidos {" + numParametros + "}"); // return false; // } // return true; // } // // protected void _$verificarTipoParametro(ArrayList paramdec) { // Node funcao = current.parent; // ArrayList parampas = current.filhos(); // int i = 0; // String tipoAtrib, tipoEsper; // try { // for (Node param : parampas) { // param = param.first(); // // tipoAtrib = Types.tipoDe(param, param.Get("tipo")); // tipoEsper = paramdec.Get(i++).Get("tipo"); // // if (tipoEsper.equals(tipoAtrib) // || tipoEsper.equals(Types.REFERENCE)) { // continue; // } // // AddError(Api.getFormatedPosition(funcao) + " Chamada de função {" // + funcao.getText() + "} invalida. Parâmetro [" + (i) + "] espera {" // + tipoEsper + "} não corresponde com a atribuição {" // + tipoAtrib + "}"); // } // } catch (Exception e) { // System.err.println(e.getMessage()); // e.printStackTrace(); // } // } // // /** // * Deve ser chamada depois de analisar uma funcao ou depois da definicao de // * uma thread Verifica:
// * -> Se quantidade de parametros // */ // protected void testarListaParametros() { // Node parent = current.parent; // ArrayList paramdec; // int numParametros = current.filhos().size(); // // if (parent.in("class", new String[]{"print", "read"})) { // return; // } // // /*Se a lista de parametros for de uma thread*/ // if (parent.igual("class", "dec::thread")) { // _$verificarQuantidadeParametros(numParametros, 1); // return; // } // // /*Se a lista de parametros for de uma função*/ // Node declaracao = Functions.function(parent.getText()); // // if (null == declaracao) { // return; // } // paramdec = declaracao.encontre("parametros").filhos(); // // /*Verifica a quantidade de parametros é igual na chamada e na declaração*/ // if (_$verificarQuantidadeParametros(numParametros, paramdec.size())) { // _$verificarTipoParametro(paramdec); // } // // } // // /** // * Verfica:
// * -> Parametros da função print,se valores e variaveis existem. // * // */ // protected void chkPrint() { // for (Node var : current.first().filhos()) { // testExist(var.first()); // } // } // // /** // * Verfica:
// * -> Parametros da função print,se valores e variaveis existem. // * // */ // protected void chkRead() { // for (Node var : current.filhos()) { // if (!var.in("class", new String[]{"var"})) { // AddErrorWithPosition("A função read exige endereços de variaveis. Especifique uma variavel para armazenar a leitura"); // } // testExist(var); // } // } // // protected void _addViolacaoDeConstante(String constante) { // AddErrorWithPosition(" Violação de contante. Tentativa de atualizar a constante {" + constante + "}."); // } // // /** // * Verfica:
// * -> Se a variavel existe.
// * -> Se o tipo da variavel é inteiro // */ // protected void chkOperacaoUnario() { // /*Se tentar operação unaria com constate*/ // if (Constantes.existe(current.getText())) { // _addViolacaoDeConstante(current.getText()); // return; // } // Node var = ast.encontreDeclaracao(current, current.parent); // if (testExist(var, true) && !var.igual("tipo", "int")) { // AddError(Api.getFormatedPosition(current) + " Tipo { " + var.getText() + " | " + var.Get("tipo") + " } não permite operação unária."); // } // } //// // // /** // * Adiciona um erro a liSta de erroS SemanticoS // * // * @param erro // */ // protected static void AddError(String erro) { // erros.add(erro); // } // // /** // * Seta a pilha do eSopo // * // * @param escopo // */ // protected void setEscopo(String escopo) { // String ant = escopoStack.empty() ? "" : "," + escopoStack.peek(); // escopoStack.push(escopo + ant); // }// // protected void DecConst() { // // } // // /** // * Verifica:
// * -> Se os operandos existem
// * -> Se tipo dos operandos sao validos
// */ // protected boolean exprArithmetic() { // int i = 1; // String type; // for (Node node : current.childrens()) { // type = tipo(node); // // if (testExist(node, false) && (!type.equals(Types.REFERENCE) && !type.equals("int"))) { // // AddError(Api.getFormatedPosition(node) + " Tipo esperado {int}. " // + " Operando {" + i + "} é do tipo {" + node.getText() + " | " + type + "}"); // return false; // } // i++; // } // return true; // } // /*Functions de apoio */ // // protected String tipo(Node n) { // switch (n.Get("class")) { // //// return n.Get("type"); // case "function::call": // Node func = encontreFuncao(n.getText(), false); // if (func != null) { // return func.Get("tipo"); // } // break; // //// case "var": //// tipo = tipoVar(n); //// break; // case "indice": // case "dec::var": // case "const": // return n.Get("type"); // // case "expr::or": // case "expr::and": // case "expr::comp": // case "value.boolean": // return Types.BOOLEAN; // // case "expr::unary": // case "expr::negative": // case "expr::arithmetic": // case "value.integer": // return Types.INTEGER; // } // return Types.UNDEFINED; // }