analisadorSintatico.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import { CommonTokenStream } from 'antlr4/index';
  2. import { SintaxError } from './SintaxError';
  3. class AnalisadorSintatico {
  4. constructor (lexer) {
  5. this.lexer = lexer;
  6. this.tokenStream = new CommonTokenStream(lexer);
  7. this.tokenStream.fill();
  8. this.pos = 1;
  9. this.variableTypes = [this.lexer.PR_INTEIRO, this.lexer.PR_REAL, this.lexer.PR_LOGICO, this.lexer.PR_CADEIA];
  10. }
  11. parseTree () {
  12. return {};
  13. }
  14. getToken (index=null) {
  15. if(index === null)
  16. index = this.pos;
  17. return this.tokenStream.LT(index);
  18. }
  19. parseProgram () {
  20. let token = null;
  21. if(this.lexer.PR_PROGRAMA === (token = this.getToken()).type) {
  22. try {
  23. this.pos++;
  24. this.consumeNewLines();
  25. parseOpenCurly();
  26. this.pos++;
  27. this.consumeNewLines();
  28. const globalVars = parseGlobalVariables();
  29. this.consumeNewLines();
  30. const functions = parseFunctions();
  31. this.consumeNewLines();
  32. parseCloseCurly();
  33. this.pos++;
  34. this.consumeNewLines();
  35. if(this.lexer.EOF !== (token = this.getToken()).type) {
  36. console.log("No extra characters are allowed after program {...}");
  37. }
  38. return {global: globalVars, functions: functions};
  39. } catch(SintaxError err) {
  40. console.log(err.message);
  41. }
  42. } else {
  43. console.log(this.getErrorString(this.lexer.literalNames(this.lexer.PR_PROGRAMA), token));
  44. }
  45. return null;
  46. }
  47. parseOpenCurly () {
  48. let token = null;
  49. if(this.lexer.ABRE_CHA !== (token = this.getToken()).type){
  50. throw new SintaxError(this.getErrorString('{', token));
  51. }
  52. }
  53. parseCloseCurly () {
  54. let token = null;
  55. if(this.lexer.FECHA_CHA !== (token = this.getToken()).type){
  56. throw new SintaxError(this.getErrorString('}', token));
  57. }
  58. }
  59. parseGlobalVariables () {
  60. let vars = [];
  61. while(true) {
  62. const decl = this.parseHasConst();
  63. const eosToken = this.getToken();
  64. if(eosToken.type !== this.lexer.EOS) {
  65. throw new SintaxError('new line or \';\'', eosToken);
  66. }
  67. this.pos++;
  68. if ( decl === null)
  69. break;
  70. else
  71. vars.push(decl);
  72. }
  73. return vars;
  74. }
  75. /*
  76. * Checks if the next token is PR_CONST. It's only available
  77. * at global variables declaration level
  78. * @returns Declararion(const, type, id, initVal?)
  79. **/
  80. parseHasConst () {
  81. const token = this.getToken();
  82. if(token.type === this.lexer.PR_CONST) {
  83. this.pos++
  84. return parseDeclararion(true);
  85. } else if(isVariableType(token)) {
  86. return parseDeclararion();
  87. } else {
  88. return null;
  89. }
  90. }
  91. /*
  92. * Parses a declarion of the form: type --- id --- (= --- EAnd)?
  93. * @returns Declararion(const, type, id, initVal?)
  94. **/
  95. parseDeclararion (isConst = false) {
  96. const typeToken = this.getToken();
  97. if(!this.isVariableType(typeToken)) {
  98. throw new SintaxError(this.variableTypes.map( x => this.lexer.literalNames[x])
  99. .reduce((o, n) => {
  100. if (o.length <= 0)
  101. return n;
  102. else
  103. return o + ", " + n;
  104. }, ''), typeToken);
  105. }
  106. this.pos++;
  107. const idToken = this.getToken();
  108. if(idToken.type !== this.lexer.ID) {
  109. throw new SintaxError('ID', idToken);
  110. }
  111. this.pos++;
  112. const equalsToken = this.getToken();
  113. if(equalsToken.type === this.lexer.ATRIBUICAO) {
  114. //process Expression
  115. } else {
  116. return {isConst: isConst, tipo: typeToken.text, id: idToken.text};
  117. }
  118. }
  119. consumeNewLines () {
  120. token = this.getToken();
  121. while(token.type === this.lexer.EOS && token.text.match('[\r\n]')) {
  122. this.pos++;
  123. token = this.getToken();
  124. }
  125. }
  126. getErrorString (symbol, token) {
  127. return `Sintax error! Expecting '${symbol}' but found ${token.text} at line:${token.line}, column:${token.column}`;
  128. }
  129. isVariableType (token) {
  130. return this.variableTypes.find(v => v === token.type);
  131. }
  132. }