Semantic.java 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218
  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 ast;
  7. import API.Functions;
  8. import common.Instruction;
  9. import API.Types;
  10. import API.Variables;
  11. import static ast.Semantic.current;
  12. import common.Log;
  13. import java.util.ArrayList;
  14. import java.util.Stack;
  15. /**
  16. *
  17. * @author Eugenio
  18. */
  19. public class Semantic extends Log {
  20. protected Stack<String> escopoStack = new Stack<>();
  21. protected AbstractSyntaxTree ast;
  22. protected static Node current;
  23. // protected HashMap<String, String> errosTemplate = new HashMap<>();
  24. // protected boolean temporalErro = false;
  25. public Semantic() {
  26. }
  27. public Semantic(AbstractSyntaxTree ast) {
  28. this.ast = ast;
  29. }
  30. /**
  31. * Percorre a AST em chama o metodo viSitNode que redireciona para o
  32. * tratamento de cada no
  33. *
  34. * @param as
  35. * @throws Exception
  36. */
  37. public Semantic Execute() throws Exception {
  38. _analise(ast.root);
  39. return this;
  40. }
  41. /**
  42. * Parte aux do metodo analiSe.
  43. *
  44. * @param n
  45. * @return
  46. * @throws Exception
  47. */
  48. protected void _analise(Node n) throws Exception {
  49. if (null == n) {
  50. return;
  51. }
  52. current = n;
  53. switch (current.Get("class")) {
  54. default:
  55. visitNode();
  56. if (!n.childrens.isEmpty()) {
  57. for (Node n2 : n.childrens) {
  58. _analise(n2);
  59. }
  60. }
  61. }
  62. }
  63. protected void visitNode() throws Exception {
  64. switch (current.Get("class")) {
  65. case "type":
  66. CheckType();
  67. break;
  68. case "selector":
  69. CheckSelector();
  70. break;
  71. case "def.assign":
  72. CheckAssign();
  73. break;
  74. case "call":
  75. CheckCall();
  76. break;
  77. case "dec.const":
  78. break;
  79. case "dec.type":
  80. break;
  81. // case "_array":
  82. //// chkArray();
  83. // break;
  84. // case "read":
  85. // chkRead();
  86. // break;
  87. // case "print":
  88. // chkPrint();
  89. // break;
  90. // case "dec::var":
  91. // verificarDecVariavel();
  92. // break;
  93. // case "return":
  94. // checkRetornoFuncao();
  95. // break;
  96. // case "var":
  97. // verificarVariavel(current);
  98. // break;
  99. // case "parametros::list":
  100. // testarListaParametros();
  101. // break;
  102. // case "op::unaria":
  103. // chkOperacaoUnario();
  104. // break;
  105. // case "expr::arithmetic":
  106. // exprArithmetic();
  107. // break;
  108. // case "exp::boolena":
  109. // chkOperacaoBooleano();
  110. // break;
  111. // case "dec::function":
  112. // case "main":
  113. // verificarFuncao();
  114. // break;
  115. }
  116. }
  117. protected void CheckType() {
  118. String type = current.Get("type");
  119. if (!Types.Primitive(type) && !Types.Defined(type)) {
  120. AddError(new Instruction()
  121. .Set("class", "Type")
  122. .Set("msg", String.format("Tipo '%s' não definido", type))
  123. .Set("line", current.Get("line"))
  124. .Set("col", current.Get("col"))
  125. );
  126. }
  127. }
  128. protected void CheckSelector() {
  129. try {
  130. String type;
  131. switch (current.Get("subclass")) {
  132. case "operand":
  133. if (!current.eq("classType", "value")
  134. && Variables.Get(current.getText()) == null) {
  135. throw new Exception("Variavel " + current.getText() + " não definida");
  136. }
  137. break;
  138. case "selector":
  139. type = Variables.TypeOf(current.Get("value"));
  140. if (type.equals("undefined")) {
  141. throw new Exception("Variavel " + current.getText() + " não definida");
  142. }
  143. // current.Set("type", type);
  144. // System.out.println("CheckSelector:" + current);
  145. break;
  146. case "index":
  147. // System.out.println("CheckSeletor:" + current);
  148. String varname = current.Get("value");
  149. type = Variables.TypeOf(varname);
  150. if (type.equals("undefined")) {
  151. throw new Exception("Variavel " + current.getText() + " não definida");
  152. }
  153. Node var = Variables.Get(varname);
  154. Node ical;
  155. ArrayList<Node> indexesCall = new ArrayList<>(current.childrens());
  156. ArrayList<Node> indexesDecl = var.childrens();
  157. if (indexesCall.size() > indexesDecl.size()) {
  158. // todo exibir os indices
  159. throw new Exception("Variavel " + current.getText() + " não aceita acesso indexado");
  160. } else {
  161. int idecval,
  162. icallval;
  163. for (Node idec : indexesDecl) {
  164. if (indexesCall.isEmpty()) {
  165. throw new Exception("Variavel " + current.getText() + " não aceita acesso indexado");
  166. }
  167. ical = indexesCall.remove(0);
  168. // se não for um indice numerico salta
  169. if (!ical.isNumber("value")) {
  170. continue;
  171. }
  172. icallval = ical.GetInt("value");
  173. idecval = idec.GetInt("value");
  174. if (idec.isNumber("value") && icallval >= idecval) {
  175. throw new Exception(String.format("Index ['%s'] fora do intervalo ['%s'] em %s", icallval, idecval, current.getText()));
  176. }
  177. }
  178. }
  179. break;
  180. }
  181. } catch (Exception e) {
  182. AddError(new Instruction()
  183. .Set("class", "Type")
  184. .Set("msg", e.getMessage())
  185. .Set("line", current.Get("line"))
  186. .Set("col", current.Get("col"))
  187. );
  188. }
  189. }
  190. protected void CheckAssign() throws Exception {
  191. ArrayList<String> returns = new ArrayList<>();
  192. Node f, funcret;
  193. for (Node attrib : current.childrens().get(1).childrens()) {
  194. switch (attrib.Class()) {
  195. case "call":
  196. f = Functions.Get(attrib.getText());
  197. funcret = f.find("dec.return");
  198. if (funcret != null) {
  199. for (Node r : funcret.childrens()) {
  200. returns.add(r.Get("type"));
  201. }
  202. }
  203. break;
  204. default:
  205. returns.add(attrib.Get("type"));
  206. break;
  207. }
  208. }
  209. ArrayList<Node> dsts = current.childrens().get(0).childrens();
  210. if (dsts.size() != returns.size()) {
  211. throw new Exception(String.format("Atribuição incompativel. Esperando %d e atribuido %d", dsts.size(), returns.size()));
  212. } else {
  213. int i = 0;
  214. String attrib, typedst;
  215. for (Node dst : dsts) {
  216. attrib = returns.get(i++);
  217. // typedst = dst.Get("type");
  218. typedst = typeoOf(dst);
  219. if (!typedst.equals(attrib)) {
  220. AddError(new Instruction()
  221. .Set("class", "Assing")
  222. .Set("msg", String.format("Tipo atribuição '%s' diferente do esperado '%s'", attrib, typedst))
  223. .Set("line", current.Get("line"))
  224. .Set("col", current.Get("col"))
  225. );
  226. }
  227. }
  228. // System.out.println("CheckAssign:" + returns);
  229. // A quantidade de retornos é igual a de destinos, verificar o tipo de cada atribuição
  230. }
  231. }
  232. protected String typeoOf(Node n) throws Exception {
  233. // System.out.println("TYPEOF:\n" + n.getText() + "\n[" + Variables.TypeOf(n.getText()) + "]");
  234. if (n.eq("type", "")) {
  235. // Variables.type(n.getText(), n.Get("scope"));
  236. n.Set("type", Variables.TypeOf(n.getText()));
  237. }
  238. return n.Get("type");
  239. }
  240. protected void CheckCall() throws Exception {
  241. // System.out.println("CheckCall:" + current);
  242. Node function = Functions.Get(current.getText());
  243. // Verifica se a funcao foi definida
  244. if (function == null) {
  245. AddError(new Instruction()
  246. .Set("class", "Call")
  247. .Set("msg", String.format("A função '%s' não foi definida", current.getText()))
  248. .Set("line", current.Get("line"))
  249. .Set("col", current.Get("col"))
  250. );
  251. return;
  252. }
  253. // Se a definicao contem argumentos verifica se na chamada possui o mesmo
  254. // numero de argumentos e se são do mesmo tipo
  255. ArrayList<Node> argumentsDelc = function.findAll("argument", "class");
  256. ArrayList<String> argsDelc = new ArrayList<>();
  257. String type, pointer;
  258. Node t;
  259. for (Node args : argumentsDelc) {
  260. t = args.find("type");
  261. type = t.Get("type");
  262. pointer = t.Get("pointer");
  263. for (int i = 0; i < args.find("ids").childrens().size(); i++) {
  264. argsDelc.add((pointer.equals("") ? "" : "&") + type);
  265. }
  266. }
  267. Node argumentsCall = current.find("arguments").find("exprs");
  268. ArrayList<String> argsCall = new ArrayList<>();
  269. if (argumentsCall != null) {
  270. String prefix = "";
  271. for (Node argCall : argumentsCall.childrens()) {
  272. // System.out.println("ArgCall:" + argCall);
  273. if (argCall.eq("subclass", "address") || argCall.eq("pointer", "*")) {
  274. prefix = "&";
  275. }
  276. argsCall.add(prefix + argCall.Get("type"));
  277. }
  278. }
  279. int argsDeclCount = argsDelc.size();
  280. int argsCallCount = argsCall.size();
  281. if (argsCallCount != argsDeclCount) {
  282. AddError(new Instruction()
  283. .Set("class", "Call")
  284. .Set("msg", String.format("Chamada incompativel. Numero de parametros de chamada é '%s' e o esperado é '%s'", argsCallCount, argsDeclCount))
  285. .Set("line", current.Get("line"))
  286. .Set("col", current.Get("col"))
  287. );
  288. } else {
  289. // todo check types
  290. int i = 0;
  291. String callType;
  292. for (String declType : argsDelc) {
  293. callType = argsCall.get(i++);
  294. // System.out.println("Call arg:" + callType + ":" + declType);
  295. if (!declType.equals(callType)) {
  296. AddError(new Instruction()
  297. .Set("class", "Call")
  298. .Set("msg", String.format("Chamada incompativel. O parâmetro %s é do tipo '%s' e o esperado é '%s'", i, callType, declType))
  299. .Set("line", current.Get("line"))
  300. .Set("col", current.Get("col"))
  301. );
  302. }
  303. }
  304. }
  305. }
  306. }
  307. // /**
  308. // * Busca uma declaração de uma função, caso não exista adiciona erro ao Log
  309. // *
  310. // * @param nomeDaFuncao
  311. // * @param AddError
  312. // * @return Node | null
  313. // */
  314. // protected static Node encontreFuncao(String id, boolean AddError) {
  315. // Node func = null;
  316. // if (id.substring(0, 2).equals("__")) {
  317. //
  318. // } else if (Functions.existe(id)) {
  319. // func = Functions.function(id);
  320. // }
  321. // if (func == null && AddError) {
  322. // AddError(Api.getFormatedPosition(current)
  323. // + "Chamada de função. Tentativa de chamar uma função {"
  324. // + id + "} não definida.");
  325. // }
  326. // return func;
  327. // }
  328. //
  329. // protected void chkOperacaoBooleano() {
  330. // Node n1 = getOperandoNaAst(current.getFilho(0), current);
  331. // Node n2 = getOperandoNaAst(current.getFilho(1), current);
  332. //
  333. // if (n1 == null || n2 == null) {
  334. // return;
  335. // }
  336. //
  337. // String esperado = "";
  338. // String tipo1 = tipo(n1);
  339. // String tipo2 = tipo(n2);
  340. //
  341. // if (current.in("value", new String[]{"==", "!="})) {
  342. // if (!tipo1.equals(tipo2)) {
  343. // AddError(Api.getFormatedPosition(current) + " Comparação invalida. "
  344. // + "Comparação entre tipos diferentes. Param[1] do tipo {" + tipo1 + "} Param[2] do tipo {" + tipo2 + "}");
  345. // }
  346. // } else {
  347. // if (current.in("value", new String[]{"<", ">", "<=", ">="})) {
  348. // esperado = "int";
  349. // } else if (current.in("value", new String[]{"&&", "||"})) {
  350. // esperado = "bool";
  351. // }
  352. // String op = current.getText();
  353. // tipoCheck(n1, tipo1, esperado, op);
  354. // tipoCheck(n2, tipo2, esperado, op);
  355. // }
  356. // }
  357. //
  358. // /**
  359. // * Verifica:<br>
  360. // * -> Operação de atribuição. -> Se o endereço de destino é valido, seja
  361. // * variavel ou declarcao de uma -> Se o tipo atribuido corresponde com o
  362. // * esperado
  363. // *
  364. // * @throws Exception
  365. // */
  366. // protected void chkAssign(Node current) throws Exception {
  367. // Node parent = current.parent;
  368. //
  369. // /**
  370. // * Se parent for igual assign::op entao deve se analisar a variavel,
  371. // * caso contrario sera dec::var e não precisa verificar o acesso a
  372. // * variavel
  373. // */
  374. // Node var;
  375. // boolean isDeclaracao = true;
  376. // if (parent.igual("class", "assign::op")) {
  377. // isDeclaracao = false;
  378. // if (Constantes.existe(parent.getText())) {
  379. // _addViolacaoDeConstante(parent.getText());
  380. // return;
  381. // }
  382. // var = parent.encontreByClass("var");
  383. // _analise(var);
  384. //
  385. // } else {
  386. // var = parent;
  387. // }
  388. //
  389. // /**
  390. // * Apos verificar variavel, vamos verificar se o tipo atribuido é igual
  391. // * ao esperado;
  392. // */
  393. // Node value = current.first();
  394. //
  395. // /*Se valor for uma variavel e a mesma não existir*/
  396. //// value.Set("verificador", "0");
  397. // _analise(value);
  398. // /*Se ocorreu erro na verificação do valor atribuido*/
  399. ////
  400. // String eTipo = parent.Get("tipo"), aTipo = tipo(value);
  401. //
  402. // if (var.igual("tipo", Types.REFERENCE)) {
  403. // if (isDeclaracao && value.diferente("acessoEndereco", "true")) {
  404. // AddError(Api.getFormatedPosition(value) + " Atribuição invalida. Reference ainda não aponta para uma área de memoria valida!");
  405. // }
  406. // return;
  407. // }
  408. //
  409. // if (!aTipo.equals(eTipo)) {
  410. // AddError(Api.getFormatedPosition(value) + " Atribuição invalida. Tipo esperado {"
  411. // + eTipo + "} enquanto o atribuido foi {" + aTipo + "}.");
  412. // }
  413. //
  414. // }
  415. //
  416. // //--------------------------------------------------//
  417. //
  418. //
  419. // //##################################################//
  420. // /**
  421. // * Verifica: <br>
  422. // * -> Se uma variavel foi redeclara.
  423. // *
  424. // * @param nome
  425. // */
  426. // protected boolean _$RedeclaracaoVar(String nome, Node current) throws Exception {
  427. // ArrayList<Node> declaracoes = current
  428. // .closest("atributos,dec::function,dec::thread,dec::globais,trap", "class")
  429. // .encontreTodos("dec::var", "class");
  430. //// filtrarFilhosPorClass();
  431. // int cId = current.GetInt("id");
  432. // int tId;
  433. // for (Node node : declaracoes) {
  434. // tId = node.GetInt("id");
  435. // if (tId >= cId) {
  436. // break;
  437. // }
  438. // if (node.igual("value", nome)) {
  439. // AddErrorWithPosition(" Redeclaração [ Variavel {" + nome
  440. // + "}]. Primeira definição na linha {" + node.Get("line") + "}");
  441. // return true;
  442. // }
  443. // }
  444. // return false;
  445. //
  446. // }
  447. //
  448. // /**
  449. // * Verifica:<br>
  450. // * -> Redeclaração de uma função no mesmo escopo
  451. // *
  452. // * @throws Exception
  453. // */
  454. // protected void _checkRedeclaracaoFuncao() throws Exception {
  455. // String nomeFuncao = current.getText();
  456. // ArrayList<Node> funcoes = current.parent.filtrarFilhosPorClass("dec::function");
  457. // int cId = current.GetInt("id");
  458. // int tId;
  459. // for (Node node : funcoes) {
  460. // tId = node.GetInt("id");
  461. // if (tId >= cId) {
  462. // break;
  463. // }
  464. // if (node.igual("value", nomeFuncao)) {
  465. // AddError(Api.getFormatedPosition(current) + "Redeclaração de função. Previa declaração na linha {" + node.Get("line") + "}");
  466. // return;
  467. // }
  468. // }
  469. // }
  470. //
  471. // protected void _verificarAtribuicaoVetor(Node variavel, Node valor) throws Exception {
  472. //// System.out.println("Var:" + variavel.encontre("indices"));
  473. //
  474. // String tipoEsperado = variavel.Get("tipo");
  475. // Node indices = variavel.encontre("indices");
  476. // int numeroIndices = indices.getChildrenCount();
  477. //
  478. //// System.out.println("\n\nAtribuicao:" + current);
  479. //// Node valor = current.getPrimeiroFilho();
  480. //// System.out.println("valor:" + valor);
  481. // if (!valor.igual("class", "lista")) {
  482. // String tipo = valor.Get("tipo");
  483. // AddErrorWithPosition("Atribuição invalida. Aguardando uma lista de "
  484. // + tipoEsperado + ". Um(a) {" + tipo + "} foi atribuido.");
  485. // return;
  486. // }
  487. //// System.out.println("Valor era matrix:" + valor.igual("matrix", "true"));
  488. // Node visit;
  489. // if (numeroIndices > 1 && !valor.igual("matrix", "true")) //Caso tenha mais de uma linha de inicializacao
  490. // {
  491. //// System.out.println("ATRIB:" + valor);
  492. // AddErrorWithPosition(" Numero de itens não corresponde ao esperado. Esperado {" + numeroIndices + "} atribuido {1}");
  493. // return;
  494. // }
  495. // if (valor.igual("matrix", "true")) {
  496. // visit = valor;
  497. // } else { //Caso seja apenas um vetor
  498. //// valor:[value: lista, id: 17, _pos: 0, class: lista, tipo: array, line: 14, col: 16, file: program::exemplo, ][1,3,] sem ()
  499. //// valor:[value: lista, id: 17, _pos: 0, class: lista, tipo: array, line: 14, col: 16, file: program::exemplo, ][lista,] ()
  500. //
  501. //// valor:[value: lista, id: 8, _pos: 0, class: lista, tipo: array, line: 14, col: 14, file: program::exemplo, ][1,2,]
  502. //// valor:[value: lista, id: 8, _pos: 0, class: lista, tipo: array, line: 14, col: 14, file: program::exemplo, ][lista,]
  503. //// System.out.println("valor:" + valor);
  504. // Node lista = valor.first();
  505. // if (lista.igual("class", "lista")) {
  506. // visit = lista;
  507. // } else {
  508. // visit = valor;
  509. // }
  510. // }
  511. // __conferirListaAtribuicao(indices, visit, 0, tipoEsperado, numeroIndices);
  512. // }
  513. //
  514. // protected void __conferirListaAtribuicao(Node indices, Node valor, int ind, String tipo, int numeroIndices) throws Exception {
  515. //// System.out.println("Valores:" + valor);
  516. // if (!indices.temFilho(ind)) {
  517. // return;
  518. // }
  519. // int numEle = indices.getFilho(ind).GetInt("value");
  520. // int numAtrib = valor.getChildrenCount();
  521. //
  522. // if (numeroIndices == 1) { //diz que e um vetor;
  523. // if (numEle != numAtrib) {
  524. // AddErrorWithPosition(" Numero de itens não corresponde ao esperado. Esperado {"
  525. // + numEle + "} atribuido {" + numAtrib + "}.");
  526. // }
  527. // checkTipo(tipo, valor.filhos(), "");
  528. // } else { //diz que é uma matrix
  529. //// System.out.println("ASDASD:" + ind + ":" + (numeroIndices - 1));
  530. // if (numEle != numAtrib) {
  531. // AddErrorWithPosition(" Numero de itens não corresponde ao esperado. Esperado {"
  532. // + numEle + "} atribuido {" + numAtrib + "}.");
  533. // return;
  534. // }
  535. // if (ind == numeroIndices - 1) {
  536. // checkTipo(tipo, valor.filhos(), "");
  537. // } else {
  538. // for (Node atribuicao : valor.filhos()) {
  539. // __conferirListaAtribuicao(indices, atribuicao, ind + 1, tipo, numeroIndices);
  540. // }
  541. // }
  542. // }
  543. // }
  544. //
  545. // protected Node getOperandoNaAst(Node n, Node parent) {
  546. // if (n.eNumerico("value") || n.igual("class", "valor")) {
  547. // return n;
  548. // }
  549. // return findVariavel(n);
  550. // }
  551. //
  552. // /**
  553. // *
  554. // * @param n Sera extraido a poiscao e o texto
  555. // * @param tipo tipo do valor atribuido
  556. // * @param esperado tipo do valor esperado
  557. // * @param op operação [atribuição,]
  558. // */
  559. // protected void tipoCheck(Node n, String tipo, String esperado, String op) {
  560. // if (tipo == null) {
  561. // tipo = "undefined";
  562. // }
  563. // String acesso = (n.temAtributo("fullAccess")) ? n.Get("fullAccess") : n.getText();
  564. // if (!tipo.equals(esperado)) {
  565. // AddError(Api.getFormatedPosition(n) + " Operação { " + op + " } espera um valor ["
  566. // + esperado + "]. Parametro { " + acesso + " } é do tipo [" + tipo + "]");
  567. // }
  568. // }
  569. //
  570. //
  571. // protected static String tipoVar(Node n) {
  572. // Node nv = findVariavel(n);
  573. // String tipo = "undefined";
  574. // /*Se a variavel não existir*/
  575. // if (null == nv) {
  576. // return tipo;
  577. // }
  578. //
  579. // Node atributo = n.encontreByClass("atributo");
  580. //
  581. // /*Se não tem atributo*/
  582. // if (null == atributo) {
  583. // return n.Get("tipo");
  584. // }
  585. //
  586. // /*Se tem atributo*/
  587. // while (null != atributo) {
  588. // tipo = atributo.Get("tipo");
  589. // atributo = atributo.encontreByClass("atributo");
  590. // }
  591. // return tipo;
  592. // }
  593. //
  594. // protected static Node findVariavel(Node var) {
  595. // return findVariavel(var, true);
  596. // }
  597. //
  598. //// protected Node findVariavel(Node var, Node parent, boolean AddError) {
  599. // protected static Node findVariavel(Node var, boolean AddError) {
  600. //// if (Constantes.existe(var.getText())) {
  601. //// return Constantes.
  602. //// }
  603. // Node dec = Variables.find(var.getText(), var.Get("escopo"));
  604. // if (dec == null && AddError) {
  605. //// System.out.println("Var:" + var);
  606. //// new Exception().printStackTrace();
  607. // AddError(Api.getFormatedPosition(var) + " Tentativa de acesso identificador {" + var.getText() + "} não declarada no escopo.");
  608. // }
  609. // return dec;
  610. // }
  611. //
  612. //
  613. //
  614. // /**
  615. // *
  616. // * @param n
  617. // * @param tipoEsperado
  618. // * @param onde
  619. // * @return true se iguais e false caso sejam diferentes
  620. // */
  621. // protected boolean checkTipo(String tipoEsperado, Node n, String onde) {
  622. // if (n.igual("tipo", "undefined")) {
  623. // switch (n.Class()) {
  624. // case "var":
  625. // n = findVariavel(n);
  626. //// n = ast.encontreDeclaracao(n, n.parent);
  627. // break;
  628. // case "function::call":
  629. // n = encontreFuncao(n.getText(), true);
  630. //// n = ast.encontreFuncao(n.getText());
  631. // break;
  632. // }
  633. // }
  634. //
  635. // if (!n.igual("tipo", tipoEsperado)) {
  636. // switch (onde) {
  637. // case "retorno":
  638. // AddErrorWithPosition(" Retorno invalido. Tipo esperado {" + tipoEsperado + "} enquanto o atribuido foi {" + n.Get("tipo") + "}.");
  639. // break;
  640. // default:
  641. // AddErrorWithPosition(" Atribuição invalida. Tipo esperado {" + tipoEsperado + "} enquanto o atribuido foi {" + n.Get("tipo") + "}.");
  642. // }
  643. // return false;
  644. // }
  645. // return true;
  646. // }
  647. //
  648. // protected void checkTipo(String tipoEsperado, ArrayList<Node> nodes, String onde) {
  649. // for (Node v : nodes) {
  650. // checkTipo(tipoEsperado, v, onde);
  651. // }
  652. // }
  653. //
  654. // public static boolean testExist(Node n) {
  655. // return testExist(n, true);
  656. // }
  657. //
  658. // public static boolean testExist(Node n, boolean AddError) {
  659. // if (n == null) {
  660. // return false;
  661. // }
  662. // switch (n.Get("class")) {
  663. //// case "function::call":
  664. //// Node func = encontreFuncao(n.getText(), AddError);
  665. //// if (func != null) {
  666. //// return true;
  667. //// }
  668. //// break;
  669. //// case "dec::var":
  670. //// return true;
  671. //// case "assign::op":
  672. //// n = n.first();
  673. //// case "var":
  674. //// return findVariavel(n, AddError) != null;
  675. ////
  676. //// case "const":
  677. //// return Constantes.existe(n.getText());
  678. ////
  679. //// case "op::unaria":
  680. //// case "exp::boolena":
  681. //// case "valor":
  682. //// case "exp::aritimetica":
  683. //// return true;
  684. // }
  685. // return false;
  686. // }
  687. //
  688. // protected Node program() {
  689. // return Root().encontre("program");
  690. // }
  691. //
  692. // protected boolean _$redeclaracao(String nome, String tipo, String onde, int id) throws Exception {
  693. // for (Node c : program().encontre(onde).filhos()) {
  694. // if (nome.equals(c.getText()) && id > c.GetInt("id")) {
  695. // AddErrorWithPosition(" Redeclaração [ " + tipo + " {" + nome + "}]. Primeira definição na linha {" + c.Get("line") + "}");
  696. // return true;
  697. // }
  698. // }
  699. // return false;
  700. // }
  701. //
  702. // /**
  703. // * Verifica: <br>
  704. // * -> Se a constante é duplicada existe; <br>
  705. // * -> Se o tipo atribuido é igual ao esperado
  706. // */
  707. // protected void chkConstante() throws Exception {
  708. // /*Verificar se constante foi redeclarada*/
  709. //
  710. //// if (_$redeclaracao(current.getText(), "Constante", "constantes", current.GetInt("id"))) {
  711. //// return;
  712. //// }
  713. // }
  714. ////
  715. // /**
  716. // * Verifica: <br>
  717. // * -> Se existe uma constante com mesmo nome <br>
  718. // * -> Se o tipo existe <br>
  719. // * -> Se ocorre redeclaração da variavel
  720. // *
  721. // * @throws Exception
  722. // */
  723. // protected void verificarDecVariavel() throws Exception {
  724. // String nome = current.getText();
  725. // if (_$RedeclaracaoVar(nome, current)) {
  726. // return;
  727. // }
  728. // if (Constantes.existe(nome)) {
  729. // AddErrorWithPosition(" Declaração invalida. Variavel {" + nome + "} com mesmo identificador de uma constante.");
  730. // return;
  731. // }
  732. // _testeTipoValido(current);
  733. // /*Se for matrix avalia os limites*/
  734. // if (current.igual("matrix", "true")
  735. // && !_$indicesValidos(current, current.encontre("indices"), false)) {
  736. // }
  737. // Node assign = current.encontreByClass("assign");
  738. // if (null != assign) {
  739. // chkAssign(assign);
  740. // }
  741. // }
  742. //
  743. // /**
  744. // * Verifica se o tipo existe; Adiciona mensagem de erro caso contrario;
  745. // *
  746. // * @param n
  747. // * @return
  748. // * @throws Exception
  749. // */
  750. // protected boolean _testeTipoValido(Node n) throws Exception {
  751. // String tipo = n.Get("tipo");
  752. // boolean exit = Types.existe(tipo);
  753. // if (!exit) {
  754. // AddError(Api.getFormatedPosition(n) + " Tipo invalido. Tipo {" + tipo + "} não definido.");
  755. // }
  756. // return exit;
  757. // }
  758. //
  759. // /**
  760. // * Verifica:<br>
  761. // * -> Função com mesmo nome de uma variavel <br>
  762. // * -> Se função foi redeclarada <br>
  763. // *
  764. // * @throws Exception
  765. // */
  766. // protected void verificarFuncao() throws Exception {
  767. //
  768. // String nomeFuncao = current.getText();
  769. // if (Variables.existe(current)) {
  770. // AddErrorWithPosition("Declaração invalida. Função com mesmo nome de uma variavel {" + nomeFuncao + "}.");
  771. // }
  772. // _$redeclaracao(nomeFuncao, "Funções", "funcoes", current.GetInt("id"));
  773. //// _checkRedeclaracaoFuncao();
  774. // // _checkRetornoFuncao();
  775. // }
  776. //
  777. // /**
  778. // * Verifica:<br>
  779. // * -> Se o retorno é o mesmo esperado pela função ;
  780. // */
  781. // protected void checkRetornoFuncao() {
  782. // Node parent = current.closest("dec::function,dec::thread", "class");
  783. // /*Se não estiver dentro de uma função ou thread*/
  784. // if (null == parent) {
  785. // return;
  786. // }
  787. // /*Se estiver dentro de uma thread não verifica*/
  788. // if (parent.igual("class", "dec::thread")) {
  789. // return;
  790. // }
  791. // String tipoEsperado = parent.Get("tipo"),
  792. // tipoAtribuido = tipo(current.first());
  793. //
  794. // if (!tipoAtribuido.equals(tipoEsperado) && !tipoAtribuido.equals(Types.REFERENCE)) {
  795. // AddErrorWithPosition(" Tipo de retorno invalido. Retornando {" + tipoAtribuido + "} enquanto o esperador é {" + tipoEsperado + "}");
  796. // }
  797. // }
  798. //
  799. //
  800. // /**
  801. // * Verifica:<br>
  802. // * -> Se função existe
  803. // */
  804. // protected void chkChamadaDeFuncao() {
  805. // if (current.in("value", new String[]{"print", "read"})) {
  806. // return;
  807. // }
  808. // String id = current.getText();
  809. //
  810. // if (null == encontreFuncao(id, false)) {
  811. // AddErrorWithPosition(" Chamada de função invalida. Não foi encontrada declaração para a função ['" + id + "'].");
  812. // }
  813. // }
  814. //
  815. // /**
  816. // * Verifica:<br>
  817. // * -> Se uma variavel existe.<br>
  818. // * -> Se for matrix avalia os limites
  819. // *
  820. // * @param nome
  821. // */
  822. // protected void verificarVariavel(Node var) throws Exception {
  823. // Node dec = findVariavel(var, true);
  824. // if (null == dec) {
  825. // var.Set("verificador", "1");
  826. // return;
  827. // }
  828. // if (!_$checkAtributoAndIndices(dec, var)) {
  829. // var.Set("verificador", "1");
  830. // }
  831. // }
  832. //
  833. // /**
  834. // * Verifica:<br>
  835. // * -> Se uma atributo existe <br>
  836. // * -> Se for matrix avalia os limites
  837. // *
  838. // * @throws Exception
  839. // */
  840. // protected boolean checkAtributo(Node current) throws Exception {
  841. // if (current == null) {
  842. // return false;
  843. // }
  844. //
  845. // String tipoParent = current.parent.Get("tipo");
  846. //
  847. // if (tipoParent.equals("undefined")) {
  848. // return false;
  849. // }
  850. //
  851. // Node pTipo = Types.Get(tipoParent);
  852. // String atributo = Variables.clearName(current.getText());
  853. // Node dec = pTipo.first().encontre(atributo);
  854. // /*Verifica se o atributo existe*/
  855. // if (null == dec) {
  856. // AddErrorWithPosition(" Acesso invalido de atributo. A variavel [ "
  857. // + current.parent.getText() + " | tipo: " + pTipo.getText()
  858. // + " ] não possui o atributo {" + atributo + "}");
  859. // return false;
  860. // }
  861. // return _$checkAtributoAndIndices(dec, current);
  862. // }
  863. //
  864. // /**
  865. // * Executa recursivamente a verificação de atributos e a verificação de
  866. // * indices
  867. // *
  868. // * @param dec
  869. // * @param current
  870. // * @throws Exception
  871. // */
  872. // protected boolean _$checkAtributoAndIndices(Node dec, Node current) throws Exception {
  873. // /*Verificar array limites*/
  874. // Node indices = current.encontre("indices");
  875. // if (null != indices && !_$indicesValidos(dec, indices, true)) {
  876. // current.Set("verificador", "1");
  877. // return false;
  878. // }
  879. // Node atributo = current.encontreByClass("atributo");
  880. // /*Se tem um proxumo atributo e é array*/
  881. // if (null != atributo && dec.igual("matrix", "true")) {
  882. // Node decInd = dec.encontre("indices"),
  883. // curInd = current.encontre("indices");
  884. //
  885. // /*Isso indica que deve estar sendo accessado um array e uma variavel*/
  886. // if (null == curInd || decInd.getChildrenCount() > curInd.getChildrenCount()) {
  887. //
  888. // AddErrorWithPosition(" Acesso invalido. Tentando acessar o atributo {" + atributo.getText() + "} de um array.");
  889. // current.Set("verificador", "1");
  890. // return false;
  891. // }
  892. // }
  893. //
  894. // /*Ativa recursao dos atributos*/
  895. // if (!checkAtributo(atributo)) {
  896. // current.Set("verificador", "1");
  897. // return false;
  898. // }
  899. // return true;
  900. // }
  901. //
  902. // /**
  903. // * Verifica:<br>
  904. // * -> Se os indices são do tipo inteiro <br>
  905. // * -> Se for valor verifica se o limite é valido
  906. // *
  907. // * @param dec
  908. // * @param indicesAccess
  909. // * @param chkLimite
  910. // * @throws Exception
  911. // */
  912. // protected boolean _$indicesValidos(Node dec, Node indicesAccess, boolean chkLimite) throws Exception {
  913. // boolean valid = true;
  914. // /*Caso o a variavel não seja um matriz*/
  915. // if (!dec.igual("matrix", "true")) {
  916. // AddErrorWithPosition(" Acesso invalido. Propriedade {" + dec.getText() + "} não é um vetor.");
  917. // return false;
  918. // }
  919. // ArrayList<Node> indices = indicesAccess.filhos();
  920. // ArrayList<Node> decIndices = dec.encontre("indices").filhos();
  921. //
  922. // if (indices.size() > decIndices.size()) {
  923. // AddErrorWithPosition(" Acesso invalido. Tentando acessar indices fora do espaço da matriz.");
  924. // return false;
  925. // }
  926. //
  927. // Node decIndice;
  928. // String tIndice;
  929. // Node indice;
  930. // for (int i = 0, valIndAce, valIndDec; i < indices.size(); i++) {
  931. // indice = indices.Get(i);
  932. // tIndice = tipo(indice);
  933. //
  934. // _analise(indice);
  935. //
  936. // if (tIndice.equals("undefined")) {
  937. // valid = false;
  938. // continue;
  939. // }
  940. //
  941. // /*Verifica se o indice é inteiro */
  942. // if (!tIndice.equals("int")) {
  943. // AddErrorWithPosition(" Indice erro. Indice [" + (i + 1) + "] deve ser inteiro, {" + tIndice + "} atribuido.");
  944. // valid = false;
  945. // continue;
  946. // }
  947. // /*Quando for uma declaração não deve conferir os limites, verificação
  948. // apenas deve ser feita quando se tratar de acesso a variavel*/
  949. //
  950. // /*Verificar limite apenas quando for numero inteiro*/
  951. // if (!chkLimite || !indice.in("class", new String[]{"valor", "indice"})) {
  952. // continue;
  953. // }
  954. //
  955. // decIndice = decIndices.Get(i);
  956. // if (!decIndice.in("class", new String[]{"valor", "indice"})) {
  957. // continue;
  958. // }
  959. //
  960. // /* Quantidade de indices da chamada */
  961. // valIndAce = indice.GetInt("value");
  962. // valIndDec = decIndice.GetInt("value");
  963. //
  964. // if (valIndAce >= valIndDec) {
  965. // AddErrorWithPosition(" Indice erro. Indice [" + (i + 1) + "], valor maximo {" + (valIndDec - 1) + "}, atribuido {" + valIndAce + "}.");
  966. // valid = false;
  967. // }
  968. // }
  969. // return valid;
  970. // }
  971. //
  972. // /**
  973. // * Registra o erro caso a quantidade de parametros seja diferente da
  974. // * declarada
  975. // *
  976. // * @param numParametros
  977. // * @param sizedec
  978. // */
  979. // protected boolean _$verificarQuantidadeParametros(int numParametros, int sizedec) {
  980. // if (numParametros > sizedec) {
  981. // AddErrorWithPosition(" Chamada invalida. Função chamada com mais "
  982. // + "parametros que o declarado. Esperando {"
  983. // + sizedec + "}, atribuidos {" + numParametros + "}");
  984. // return false;
  985. // } else if (numParametros < sizedec) {
  986. // AddErrorWithPosition(" Chamada invalida. Função chamada com menos "
  987. // + "parametros que o declarado. Esperando {"
  988. // + sizedec + "}, atribuidos {" + numParametros + "}");
  989. // return false;
  990. // }
  991. // return true;
  992. // }
  993. //
  994. // protected void _$verificarTipoParametro(ArrayList<Node> paramdec) {
  995. // Node funcao = current.parent;
  996. // ArrayList<Node> parampas = current.filhos();
  997. // int i = 0;
  998. // String tipoAtrib, tipoEsper;
  999. // try {
  1000. // for (Node param : parampas) {
  1001. // param = param.first();
  1002. //
  1003. // tipoAtrib = Types.tipoDe(param, param.Get("tipo"));
  1004. // tipoEsper = paramdec.Get(i++).Get("tipo");
  1005. //
  1006. // if (tipoEsper.equals(tipoAtrib)
  1007. // || tipoEsper.equals(Types.REFERENCE)) {
  1008. // continue;
  1009. // }
  1010. //
  1011. // AddError(Api.getFormatedPosition(funcao) + " Chamada de função {"
  1012. // + funcao.getText() + "} invalida. Parâmetro [" + (i) + "] espera {"
  1013. // + tipoEsper + "} não corresponde com a atribuição {"
  1014. // + tipoAtrib + "}");
  1015. // }
  1016. // } catch (Exception e) {
  1017. // System.err.println(e.getMessage());
  1018. // e.printStackTrace();
  1019. // }
  1020. // }
  1021. //
  1022. // /**
  1023. // * Deve ser chamada depois de analisar uma funcao ou depois da definicao de
  1024. // * uma thread Verifica: <br>
  1025. // * -> Se quantidade de parametros
  1026. // */
  1027. // protected void testarListaParametros() {
  1028. // Node parent = current.parent;
  1029. // ArrayList<Node> paramdec;
  1030. // int numParametros = current.filhos().size();
  1031. //
  1032. // if (parent.in("class", new String[]{"print", "read"})) {
  1033. // return;
  1034. // }
  1035. //
  1036. // /*Se a lista de parametros for de uma thread*/
  1037. // if (parent.igual("class", "dec::thread")) {
  1038. // _$verificarQuantidadeParametros(numParametros, 1);
  1039. // return;
  1040. // }
  1041. //
  1042. // /*Se a lista de parametros for de uma função*/
  1043. // Node declaracao = Functions.function(parent.getText());
  1044. //
  1045. // if (null == declaracao) {
  1046. // return;
  1047. // }
  1048. // paramdec = declaracao.encontre("parametros").filhos();
  1049. //
  1050. // /*Verifica a quantidade de parametros é igual na chamada e na declaração*/
  1051. // if (_$verificarQuantidadeParametros(numParametros, paramdec.size())) {
  1052. // _$verificarTipoParametro(paramdec);
  1053. // }
  1054. //
  1055. // }
  1056. //
  1057. // /**
  1058. // * Verfica: <br>
  1059. // * -> Parametros da função print,se valores e variaveis existem.
  1060. // *
  1061. // */
  1062. // protected void chkPrint() {
  1063. // for (Node var : current.first().filhos()) {
  1064. // testExist(var.first());
  1065. // }
  1066. // }
  1067. //
  1068. // /**
  1069. // * Verfica: <br>
  1070. // * -> Parametros da função print,se valores e variaveis existem.
  1071. // *
  1072. // */
  1073. // protected void chkRead() {
  1074. // for (Node var : current.filhos()) {
  1075. // if (!var.in("class", new String[]{"var"})) {
  1076. // AddErrorWithPosition("A função read exige endereços de variaveis. Especifique uma variavel para armazenar a leitura");
  1077. // }
  1078. // testExist(var);
  1079. // }
  1080. // }
  1081. //
  1082. // protected void _addViolacaoDeConstante(String constante) {
  1083. // AddErrorWithPosition(" Violação de contante. Tentativa de atualizar a constante {" + constante + "}.");
  1084. // }
  1085. //
  1086. // /**
  1087. // * Verfica: <br>
  1088. // * -> Se a variavel existe. <br>
  1089. // * -> Se o tipo da variavel é inteiro
  1090. // */
  1091. // protected void chkOperacaoUnario() {
  1092. // /*Se tentar operação unaria com constate*/
  1093. // if (Constantes.existe(current.getText())) {
  1094. // _addViolacaoDeConstante(current.getText());
  1095. // return;
  1096. // }
  1097. // Node var = ast.encontreDeclaracao(current, current.parent);
  1098. // if (testExist(var, true) && !var.igual("tipo", "int")) {
  1099. // AddError(Api.getFormatedPosition(current) + " Tipo { " + var.getText() + " | " + var.Get("tipo") + " } não permite operação unária.");
  1100. // }
  1101. // }
  1102. ////
  1103. //
  1104. // /**
  1105. // * Adiciona um erro a liSta de erroS SemanticoS
  1106. // *
  1107. // * @param erro
  1108. // */
  1109. // protected static void AddError(String erro) {
  1110. // erros.add(erro);
  1111. // }
  1112. //
  1113. // /**
  1114. // * Seta a pilha do eSopo
  1115. // *
  1116. // * @param escopo
  1117. // */
  1118. // protected void setEscopo(String escopo) {
  1119. // String ant = escopoStack.empty() ? "" : "," + escopoStack.peek();
  1120. // escopoStack.push(escopo + ant);
  1121. // }//
  1122. // protected void DecConst() {
  1123. //
  1124. // }
  1125. //
  1126. // /**
  1127. // * Verifica: <br>
  1128. // * -> Se os operandos existem <br>
  1129. // * -> Se tipo dos operandos sao validos <br>
  1130. // */
  1131. // protected boolean exprArithmetic() {
  1132. // int i = 1;
  1133. // String type;
  1134. // for (Node node : current.childrens()) {
  1135. // type = tipo(node);
  1136. //
  1137. // if (testExist(node, false) && (!type.equals(Types.REFERENCE) && !type.equals("int"))) {
  1138. //
  1139. // AddError(Api.getFormatedPosition(node) + " Tipo esperado {int}. "
  1140. // + " Operando {" + i + "} é do tipo {" + node.getText() + " | " + type + "}");
  1141. // return false;
  1142. // }
  1143. // i++;
  1144. // }
  1145. // return true;
  1146. // }
  1147. // /*Functions de apoio */
  1148. //
  1149. // protected String tipo(Node n) {
  1150. // switch (n.Get("class")) {
  1151. //
  1152. //// return n.Get("type");
  1153. // case "function::call":
  1154. // Node func = encontreFuncao(n.getText(), false);
  1155. // if (func != null) {
  1156. // return func.Get("tipo");
  1157. // }
  1158. // break;
  1159. //
  1160. //// case "var":
  1161. //// tipo = tipoVar(n);
  1162. //// break;
  1163. // case "indice":
  1164. // case "dec::var":
  1165. // case "const":
  1166. // return n.Get("type");
  1167. //
  1168. // case "expr::or":
  1169. // case "expr::and":
  1170. // case "expr::comp":
  1171. // case "value.boolean":
  1172. // return Types.BOOLEAN;
  1173. //
  1174. // case "expr::unary":
  1175. // case "expr::negative":
  1176. // case "expr::arithmetic":
  1177. // case "value.integer":
  1178. // return Types.INTEGER;
  1179. // }
  1180. // return Types.UNDEFINED;
  1181. // }