Variaveis.java 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666
  1. /*
  2. * To change this license header, choose License Headers in Project Properties.
  3. * To change this template file, choose Tools | Templates
  4. * and open the template in the editor.
  5. */
  6. package API;
  7. import ast.Node;
  8. import java.util.ArrayList;
  9. import java.util.Arrays;
  10. import java.util.HashMap;
  11. import java.util.List;
  12. import java.util.Map;
  13. import java.util.regex.Matcher;
  14. import java.util.regex.Pattern;
  15. /**
  16. *
  17. * @author Eugenio
  18. */
  19. public class Variaveis {
  20. public static Integer indexCount = 0;
  21. public static HashMap<String, Node> vars;
  22. public static HashMap<String, Instruction> scopes;
  23. public static String UNDEFINED = "undefined";
  24. public static String currentKey;
  25. public static Pattern BASEVEXPR = Pattern.compile("(\\w+(\\.@\\w+)*\\.\\w+)");
  26. public static String CLEARBASEVAR = "(\\w+(\\.@\\w+)*\\.)";
  27. public static void _init() {
  28. vars = new HashMap<>();
  29. scopes = new HashMap<>();
  30. }
  31. public static void Add(String id, Node var) throws Exception {
  32. // System.out.println("AddVar:" + id + "\n" + var);
  33. if (vars.containsKey(id)) {
  34. String[] parts = id.split("\\.");
  35. throw new Exception("'" + parts[parts.length - 1] + "' previamente declarado em na linha " + vars.get(id).get("line", ""));
  36. // throw new Exception("'" + id + "' previamente declarado em na linha " + vars.get(id).get("line", ""));
  37. }
  38. var.S("public", Base.IsPublic(var.G("name")) ? "true" : "false");
  39. vars.put(id, var);
  40. }
  41. public static boolean Defined(String id) {
  42. return Defined(id, true);
  43. }
  44. public static boolean Defined(String id, boolean clear) {
  45. if (clear) {
  46. id = BaseVar(id);
  47. }
  48. // System.out.println("Defined:"+id+":"+vars.containsKey(id));
  49. return vars.containsKey(id);
  50. }
  51. public static String BaseVar(String id) {
  52. Matcher match = BASEVEXPR.matcher(id);
  53. while (match.find()) {
  54. return match.group(1);
  55. }
  56. return id;
  57. }
  58. public static String TypeOf(String varname) throws Exception {
  59. Node var = Get(varname);
  60. Node tmp, t;
  61. String type = "undefined";
  62. if (var != null) {
  63. // System.out.println("TypeOf:\n" + varname + "\n" + var + "\n" + var.contem("scope", "."));
  64. String path;
  65. if (var.contem("scope", ".")) {
  66. path = varname.replace(var.G("name"), "");
  67. } else {
  68. ArrayList<String> parts = new ArrayList<>();
  69. for (String s : var.G("name").split("\\.")) {
  70. parts.add(s);
  71. }
  72. parts.add(1, "(\\.@\\w+)+\\.");
  73. // System.out.println("PARTS:" + Utils.Join(parts, ""));
  74. path = varname.replaceFirst(Utils.Join(parts, ""), "");
  75. }
  76. // System.out.println("path:" + var.G("name") + "---" + path);
  77. // Sem path
  78. if (path.length() > 0) {
  79. ArrayList<String> parts = new ArrayList<>(Arrays.asList(path.split("\\.")));
  80. parts.remove(0); // Remove a primaira parte que é uma string vazia
  81. String typed = var.G("type"), attr;
  82. t = Tipos.Get(typed);
  83. while (parts.size() > 0) {
  84. if (Tipos.Primitive(typed)) {
  85. return typed;
  86. }
  87. if (t == null) {
  88. throw new Exception(String.format("Tipo '%s' não definido", typed));
  89. }
  90. attr = parts.remove(0);
  91. tmp = t.find(attr);
  92. if (tmp == null) {
  93. throw new Exception(String.format("Tipo '%s' não possui o atributo '%s'", typed, attr));
  94. }
  95. typed = tmp.find("type").G("type");
  96. t = Tipos.Get(typed);
  97. }
  98. // System.out.println("Type:" + t + type);
  99. type = t.G("type");
  100. } else {
  101. type = var.G("type");
  102. }
  103. }
  104. // System.out.println("Type of:" + varname + ":" + type);
  105. return type;
  106. }
  107. public static Node Get(String id) {
  108. String x = id;
  109. id = BaseVar(id);
  110. // System.out.println("Get:" + id + "=" + x);
  111. if (Defined(id, false)) {
  112. // System.out.println("Var defined:" + id);
  113. return vars.get(id);
  114. }
  115. List<String> items = Arrays.asList(id.split("\\."));
  116. // Minima representacao de uma variavel sendo o pacote e o id
  117. if (items.size() <= 2) {
  118. return null;
  119. }
  120. List<String> parts = items.subList(0, items.size() - 2);
  121. parts = new ArrayList<>(parts);
  122. parts.add(items.get(items.size() - 1));
  123. // System.out.println("Get ID:" + Utils.Join(parts, "."));
  124. return Get(Utils.Join(parts, "."));
  125. }
  126. /**
  127. * Metodos antigos
  128. */
  129. /**
  130. * Adiciona uma variavel em um eScopo
  131. *
  132. * @param name
  133. * @param type
  134. * @param scope
  135. * @param array
  136. */
  137. public static void add(String name, String type, String scope, Node n) {
  138. String key = name + ":" + scope;
  139. vars.put(key, n);
  140. if (!scopes.containsKey(scope)) {
  141. scopes.put(scope, new Instruction());
  142. }
  143. scopes.get(scope).S(name, type);
  144. }
  145. public static String type(String id, String scope) {
  146. if (exist(id, scope)) {
  147. return vars.get(currentKey).G("type");
  148. }
  149. return UNDEFINED;
  150. }
  151. /**
  152. * Retorna true Se uma variavel é aceSSivel de um determinado eScopo.
  153. *
  154. * @param name
  155. * @param scope
  156. * @return
  157. */
  158. public static boolean accessible(String name, String scope) {
  159. return type(name, scope) != UNDEFINED;
  160. }
  161. /**
  162. * Verifica Se uma variavel foi declarada em um determinado eScopo
  163. *
  164. * @param name
  165. * @param scope
  166. * @return
  167. */
  168. public static boolean exist(String name, String scope) {
  169. String key = name + ":" + scope;
  170. if (vars.containsKey(key)) {
  171. currentKey = key;
  172. return true;
  173. }
  174. String[] path = scope.split(",", 2);
  175. if (path.length == 2) {
  176. return exist(name, path[1]);
  177. }
  178. key = name + ":" + path[0];
  179. if (vars.containsKey(key)) {
  180. currentKey = key;
  181. return true;
  182. }
  183. return false;
  184. }
  185. /**
  186. * Verifica Se uma variavel foi declarada por meio do no da AST
  187. *
  188. * @param nome
  189. * @param escopo
  190. * @return
  191. */
  192. public static boolean exist(Node var) {
  193. return exist(var.getText(), var.G("scope"));
  194. }
  195. public static Node get(Node n) {
  196. return exist(n) ? vars.get(currentKey) : null;
  197. }
  198. public static Node get(String name, String scope) {
  199. return exist(name, scope) ? vars.get(currentKey) : null;
  200. }
  201. public static String printScope(String scope) {
  202. if (!scopes.containsKey(scope)) {
  203. return "Scope " + scope + " não definido!";
  204. }
  205. return "Scope{" + scope + "}\n" + scopes.get(scope);
  206. }
  207. /**
  208. *
  209. * DAQUI PRA CIMA O RESTO APAGA
  210. *
  211. *
  212. */
  213. /**
  214. * Verifica Se uma dada variavel é um array
  215. *
  216. * @param varname
  217. * @return
  218. */
  219. public static boolean isArray(String varname) {
  220. return (varname.lastIndexOf("[") >= 0);
  221. }
  222. public static String clearName(String nome) {
  223. return nome.split("\\[")[0].replace("&", "");
  224. }
  225. // /**
  226. // * Retorna uma variavel em um dado escopo do programa
  227. // *
  228. // * @param nome nome da variavel
  229. // * @param escopo escopo da variavel (onde foi declarada)
  230. // * @return Node | null
  231. // * @throws Exception
  232. // */
  233. // public static Node var(String nome, String escopo) {
  234. // existe(nome, escopo);
  235. // return varsNodes.G(index.G(baseName(nome) + ":" + escopo));
  236. //
  237. // }
  238. //
  239. // /**
  240. // * Adiciona uma variavel em um dado escopo do programa
  241. // *
  242. // * @param nome nome da variavel
  243. // * @param escopo escopo da variavel (onde foi declarada)
  244. // * @param var no com todos os dados da variavel
  245. // * @throws Exception
  246. // */
  247. // public static void var(String nome, String escopo, Node var) {
  248. // existe(nome, escopo);
  249. // varsNodes.put(index.G(baseName(nome) + ":" + escopo), var);
  250. // }
  251. //
  252. // public static String tipo(Node variavel) {
  253. // return tipo(variavel.G("value"), variavel.G("escopo"));
  254. // }
  255. // public static String tipo(String nome, String escopo) {
  256. // nome = baseName(nome);
  257. // try {
  258. // existe(nome, escopo);
  259. // return types.G(index.G(nome + ":" + escopo));
  260. // } catch (Exception e) {
  261. // return _tipo(nome, escopo);
  262. // }
  263. // }
  264. // protected static String _tipo(String nome, String escopo) {
  265. // nome = baseName(nome);
  266. // try {
  267. // String[] escopos = escopo.split(",", 2);
  268. // if (escopos.length == 2) {
  269. // return tipo(nome, escopos[1]);
  270. // }
  271. // existe(nome, escopos[0]);
  272. // return types.G(index.G(nome + ":" + escopos[0]));
  273. // } catch (Exception e) {
  274. // return null;
  275. // }
  276. // }
  277. // /**
  278. // * Retorna uma variavel do escopo, caso não a encontre vai buscar no escopo
  279. // * pai. Se chegar ao no root e não encontrar a variavel, será retornado o
  280. // * valor null.
  281. // *
  282. // * @param nome
  283. // * @param escopo
  284. // * @return
  285. // */
  286. // public static Node find(Node variavel) {
  287. // if (variavel == null) {
  288. // return null;
  289. // }
  290. // return find(variavel.getText(), variavel.G("escopo"));
  291. // }
  292. //
  293. // /**
  294. // * Retorna uma variavel do escopo, caso não a encontre vai buscar no escopo
  295. // * pai. Se chegar ao no root e não encontrar a variavel, será retornado o
  296. // * valor null.
  297. // *
  298. // * @param nome
  299. // * @param escopo
  300. // * @return
  301. // */
  302. // public static Node find(String nome, String escopo) {
  303. // nome = baseName(nome);
  304. // return existe(nome, escopo)
  305. // ? varsNodes.G(index.G(nome + ":" + escopo))
  306. // : _find(nome, escopo);
  307. // }
  308. // /**
  309. // * Auxiliar do metodo find
  310. // *
  311. // * @param nome
  312. // * @param escopo
  313. // * @return
  314. // */
  315. // protected static Node _find(String nome, String escopo) {
  316. // nome = baseName(nome);
  317. // String[] escopos = escopo.split(",", 2);
  318. // if (escopos.length == 2) {
  319. // return find(nome, escopos[1]);
  320. // }
  321. // return existe(nome, escopos[0])
  322. // ? varsNodes.G(index.G(nome + ":" + escopos[0]))
  323. // : null;
  324. // }
  325. // /**
  326. // * Retorna o escopo onde a variavel foi declarada.
  327. // *
  328. // * @param nome
  329. // * @param escopo
  330. // * @return
  331. // */
  332. // public static String declaracao(String nome, String escopo) {
  333. // nome = baseName(nome);
  334. // try {
  335. // existe(nome, escopo);
  336. // return escopo;
  337. // } catch (Exception e) {
  338. // return _declaracao(nome, escopo);
  339. // }
  340. // }
  341. //
  342. // /**
  343. // * Auxiliar do metodo declaracao.
  344. // *
  345. // * @param nome
  346. // * @param escopo
  347. // * @return
  348. // */
  349. // protected static String _declaracao(String nome, String escopo) {
  350. // nome = baseName(nome);
  351. // try {
  352. // String[] escopos = escopo.split(",", 2);
  353. // if (escopos.length == 2) {
  354. // return declaracao(nome, escopos[1]);
  355. // }
  356. // existe(nome, escopos[0]);
  357. // return escopos[0];
  358. // } catch (Exception e) {
  359. // return null;
  360. // }
  361. // }
  362. // public static void var(int cod, Node var) {
  363. // varsNodes.put(cod, var);
  364. // }
  365. public static String baseName(String text) {
  366. return clearName(text).split("\\.")[0];
  367. }
  368. public static void print() {
  369. String str = "Variaveis\n";
  370. for (Map.Entry<String, Node> entry : vars.entrySet()) {
  371. String varKey = entry.getKey();
  372. Node value = entry.getValue();
  373. str += "\n" + value;
  374. }
  375. System.out.println(str);
  376. }
  377. // /**
  378. // * Testa ocorrencia de uma variavel, verifica se a mesma existe e se o tipo
  379. // * corresponde com o esperado.
  380. // *
  381. // * @param current
  382. // * @param tipoEsperado
  383. // */
  384. // public static boolean teste(Node current, String tipoEsperado) {
  385. // /*Verifica se existe declaracao da variavel*/
  386. // String varpath = current.getText();
  387. // existe(varpath, current.G("escopo"));
  388. //
  389. //// if (Tipos.structAcesso(varpath)) {
  390. //// Tipos.validarAtribuicao(current);
  391. //// }
  392. // Node var = find(varpath, current.G("escopo"));
  393. // if (!var.G("tipo").equals(tipoEsperado)) {
  394. // return false;
  395. // }
  396. // return true;
  397. //
  398. // }
  399. // static String getFullName(Node param) {
  400. // System.out.println("\n\nFULL:" + param);
  401. // String indices = "";
  402. // Node indicesNodes = param.encontre("indices");
  403. // if (null != indicesNodes) {
  404. // for (Node ind : indicesNodes.filhos()) {
  405. // indices += "[" + ind.getText() + "]";
  406. // }
  407. // }
  408. // return param.getText() + indices;
  409. // }
  410. // protected static void verificarIndices(ArrayList<Node> acessoIndices) {
  411. // for (Node indice : acessoIndices) {
  412. // if (!indice.isNumber("value")) {
  413. // AnalizadorSemantico.testExist(indice);
  414. // }
  415. // }
  416. // }
  417. // public static void acessoMatrixIsValid(Node var) throws Exception {
  418. // String tipoParent = var.parent.G("tipo");
  419. // String atributo = ivannosysUtils.clearName(var.getText());
  420. // int limit, acesso, i = 0;
  421. //
  422. // Node indices = var.encontre("indices");
  423. //
  424. // /*Caso não seja acessado nenhum indice da matrix return*/
  425. // if (null == indices) {
  426. // return;
  427. // }
  428. //
  429. // ArrayList<Node> acessoIndices = indices.filhos();
  430. //
  431. // verificarIndices(acessoIndices);
  432. //
  433. // /*Se for declaração apenas verifica se indices são corretos*/
  434. // if (var.igual("class", "dec::var")) {
  435. // return;
  436. // }
  437. // /*Se for acesso de uma variavel e possuir indices verificar se os mesmos estao dentro dos limites*/
  438. // ArrayList<String> decIndices;
  439. // boolean isAtributo = var.igual("class", "atributo");
  440. // decIndices = isAtributo
  441. // ? Tipos.getIndices(var) : Variaveis.getIndices(var);
  442. // limit = decIndices.size();
  443. // acesso = acessoIndices.size();
  444. //
  445. //// if (acesso < limit) {
  446. //// throw new Exception(Api.getFormatedPosition(var) + " Matriz acesso invalido. "
  447. //// + "Quantidade de indices inferior ao da matriz");
  448. //// } else
  449. //// System.out.println("VAR:" + var.getText() + ",limit:" + limit + ", acesso:" + acesso);
  450. // if (acesso > limit) {
  451. // throw new Exception(Api.getFormatedPosition(var) + " Matriz acesso invalido. "
  452. // + "Quantidade {" + acesso + "} de indices superior ao da matriz {" + limit + "} ");
  453. // }
  454. // if (decIndices.size() != 0) {
  455. // return;
  456. // }
  457. //
  458. // for (Node indice : acessoIndices) {
  459. // if (indice.isNumber("value")) {
  460. // limit = Integer.parseInt(decIndices.G(i));
  461. // acesso = indice.getInt("value");
  462. // if (acesso >= limit || acesso < 0) {
  463. // throw new Exception("Acesso indevido a um array, limite {"
  464. // + (limit - 1) + "} enquanto a tentativa foi {"
  465. // + acesso + "} na posição {" + i + "}");
  466. //
  467. // }
  468. // }
  469. // i++;
  470. // }
  471. //
  472. // Node attr = var.encontreByClass("atributo");
  473. // if (null == attr) {
  474. // return;
  475. // }
  476. // if (!temAtributo(tipoParent, atributo)) {
  477. // throw new Exception(" Acessando atributo [" + atributo + "] não definido no tipo[" + tipoParent + "]");
  478. // }
  479. //
  480. // acessoMatrixIsValid(attr);
  481. //
  482. // }
  483. //
  484. // public static ArrayList<String> getIndices(Node var) {
  485. // Node declaracao = find(var);
  486. // ArrayList<String> indices = new ArrayList<>();
  487. // for (Node n : declaracao.encontre("indices").filhos()) {
  488. // indices.add(n.getText());
  489. // }
  490. // return indices;
  491. // }
  492. //
  493. // public static boolean isMagica(String nome) {
  494. // return nome.matches("__.*__(\\[.*\\])*");
  495. // }
  496. // /**
  497. // * Verfica se todos os indices do acesso são numericos
  498. // *
  499. // * @param var
  500. // * @return
  501. // */
  502. // public static boolean todosIndicesNumericos(Node var) {
  503. // Node indices = var.encontre("indices");
  504. // if (null != indices) {
  505. // for (Node n : indices.filhos()) {
  506. // if (!n.isNumber("value")) {
  507. // return false;
  508. // }
  509. // }
  510. // }
  511. // Node atributo = var.encontreByClass("atributo");
  512. // return (null != atributo) ? todosIndicesNumericos(atributo) : true;
  513. // }
  514. //
  515. // public static int tamanhoVetor(Node n) throws Exception {
  516. // Node indices = n.encontre("indices");
  517. // int size = 1;
  518. // if (null != indices) {
  519. // for (Node indice : indices.filhos()) {
  520. // size *= indice.getInt("value");
  521. // }
  522. // }
  523. // return size;
  524. // }
  525. public static void List() {
  526. StringBuilder s = new StringBuilder();
  527. Node v;
  528. String index, constant, Public;
  529. for (String var : vars.keySet()) {
  530. index = "";
  531. constant = "";
  532. v = vars.get(var);
  533. if (v.eq("constant", "true")) {
  534. constant = "constant";
  535. }
  536. Public = v.eq("public", "true") ? "public" : "private";
  537. for (Node i : v.childrens()) {
  538. index += "[" + i.getText() + "]";
  539. }
  540. s.append(var + ": " + index + v.G("type") + " [" + Public + " " + constant + "]\n");
  541. }
  542. System.out.println("Vars:\n" + s.toString());
  543. }
  544. public static String Type(String id) {
  545. Node var = Get(id);
  546. if (var == null) {
  547. return "undefined";
  548. }
  549. return var.G("type");
  550. }
  551. public static int Shift(String id) {
  552. Node var = Get(id);
  553. if (var == null) {
  554. return 0;
  555. }
  556. // System.out.println("Var Shift:" + id);
  557. String[] varparts = var.getText().split("\\.");
  558. String varname = varparts[varparts.length - 1];
  559. String[] idparts = id.split(varname + "\\.?");
  560. if (idparts.length == 2) {
  561. ArrayList<String> path = new ArrayList<>(Arrays.asList(idparts[1].split("\\.")));
  562. // System.out.println("shift:" + var.G("type") + "-" + path);
  563. return Tipos.Shift(var.G("type"), path);
  564. }
  565. // Não é acesso a um atributo
  566. return 0;
  567. }
  568. }
  569. // Node attrib = getAtributo(tipoParent, atributo);
  570. // if (attrib.igual("matrix", "false")) {
  571. // throw new Exception("Atributo [" + atributo + "] não é matrix");
  572. // return;
  573. // }
  574. //
  575. // int i = 0, limit, limitCall, acesso;
  576. // ArrayList<Node> tipoIndices = new ArrayList<>();
  577. //
  578. // String atributo = ivannosysUtils.clearName(var.getText());
  579. // boolean eDeclaracao = var.igual("class", "dec::var");
  580. // if (!eDeclaracao) {
  581. //
  582. // if (!temAtributo(tipoParent, atributo)) {
  583. // throw new Exception(" Acessando atributo [" + atributo + "] não definido no tipo[" + tipoParent + "]");
  584. // }
  585. //
  586. // Node attrib = getAtributo(tipoParent, atributo);
  587. //
  588. // if (attrib.igual("matrix", "false")) {
  589. // if (!acessoIndices.isEmpty()) {
  590. // throw new Exception("Atributo [" + atributo + "] não é matrix");
  591. // }
  592. // return;
  593. // }
  594. // tipoIndices = attrib.encontre("indices").getChildrens();
  595. // }
  596. //
  597. // for (Node indice : acessoIndices) {
  598. // if (!indice.eNumerico("value")) {
  599. // AnalizadorSemantico.testExist(indice);
  600. // continue;
  601. // } else if (!eDeclaracao) {
  602. // limit = tipoIndices.G(i).getInt("value");
  603. // acesso = indice.getInt("value");
  604. // if (acesso >= limit || acesso < 0) {
  605. // throw new Exception("Acesso indevido a um array, limite {"
  606. // + (limit - 1) + "} enquanto a tentativa foi {"
  607. // + acesso + "} na posição {" + i + "}");
  608. //
  609. // }
  610. // }
  611. // i++;
  612. // }