parseFromVisual.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. import { IVProgParser } from "../ast/ivprogParser";
  2. import * as Expressions from "../ast/expressions";
  3. import { Types } from "../typeSystem/types";
  4. import { convertBoolToString } from "../typeSystem/parsers";
  5. import * as Commands from "../ast/commands";
  6. import { ArrayType } from "../typeSystem/array_type";
  7. const TYPES = {
  8. VARIABLE: "var",
  9. CONST: "const",
  10. FUNCTION: "function",
  11. RELATIONAL: "relational",
  12. LOGIC: "logic",
  13. ARITHMETIC: "arithmetic",
  14. };
  15. function translateOp (type, op) {
  16. switch (type) {
  17. case TYPES.ARITHMETIC:
  18. return op.value;
  19. case TYPES.RELATIONAL:
  20. return op.value;
  21. case TYPES.LOGIC: {
  22. if (op.ord === 11) {
  23. return "and";
  24. } else if (op.ord === 12) {
  25. return "or";
  26. } else {
  27. return "not";
  28. }
  29. }
  30. }
  31. }
  32. function getOpType (op) {
  33. switch (op.ord) {
  34. case 0:
  35. case 1:
  36. case 2:
  37. case 3:
  38. case 4:
  39. return TYPES.ARITHMETIC;
  40. case 5:
  41. case 6:
  42. case 7:
  43. case 8:
  44. case 9:
  45. case 10:
  46. return TYPES.RELATIONAL;
  47. default:
  48. return TYPES.LOGIC;
  49. }
  50. }
  51. /**
  52. * @param {Commands.Function} func
  53. * */
  54. function functionWalker (func) {
  55. const funcDeclaration = {
  56. name: func.name,
  57. return_type: "",
  58. return_dimensions: 0,
  59. parameters_list: [],
  60. variables_list: [],
  61. commands: [],
  62. };
  63. if (func.returnType instanceof ArrayType) {
  64. funcDeclaration.return_type = func.returnType.innerType.value;
  65. funcDeclaration.return_dimensions = func.returnType.dimensions;
  66. } else {
  67. funcDeclaration.return_type = func.returnType.value;
  68. }
  69. funcDeclaration.parameters_list = func.formalParameters.map(
  70. functionParameterWalker
  71. );
  72. funcDeclaration.variables_list = func.variablesDeclarations.map(
  73. variableDeclarationWalker
  74. );
  75. return funcDeclaration;
  76. }
  77. /**
  78. * @param {Commands.FormalParameter} formalParameter
  79. * */
  80. function functionParameterWalker (formalParameter) {
  81. const variable = {
  82. name: formalParameter.id,
  83. type: "",
  84. rows: 0,
  85. columns: 0,
  86. dimension: 0,
  87. value: 0,
  88. is_const: false,
  89. reference: formalParameter.byRef,
  90. };
  91. if (formalParameter.type instanceof ArrayType) {
  92. variable.type = formalParameter.type.innerType.value;
  93. variable.dimension = formalParameter.type.dimensions;
  94. } else {
  95. variable.type = formalParameter.type.value;
  96. }
  97. return variable;
  98. }
  99. /**
  100. * @param {Commands.Declaration} command
  101. * @param {boolean} global
  102. * */
  103. function variableDeclarationWalker (command, global = false) {
  104. const variable = {
  105. name: command.id,
  106. type: "",
  107. rows: 0,
  108. columns: 0,
  109. dimension: 0,
  110. value: 0,
  111. is_const: false,
  112. };
  113. variable.is_const = global && command.isConst;
  114. if (command instanceof Commands.ArrayDeclaration) {
  115. // array
  116. const lines = expressionWalker(command.lines).pop();
  117. variable.type = command.type.innerType.value;
  118. if (command.isVector) {
  119. variable.rows = 1;
  120. variable.columns = lines.value;
  121. variable.dimension = 1;
  122. const values = command.initial.map(
  123. (exp) => expressionWalker(exp).pop().value
  124. );
  125. variable.value = values;
  126. } else {
  127. const columns = expressionWalker(command.columns).pop();
  128. variable.dimension = 2;
  129. variable.rows = lines.value;
  130. variable.columns = columns.value;
  131. const values = command.initial.map((rows) =>
  132. rows.map((exp) => expressionWalker(exp).pop().value)
  133. );
  134. variable.value = values;
  135. }
  136. } else {
  137. // atomic
  138. variable.type = command.type.value;
  139. variable.value = expressionWalker(command.initial).pop().value;
  140. }
  141. return variable;
  142. }
  143. /**
  144. *
  145. * @return {[]}
  146. **/
  147. function expressionWalker (expression) {
  148. let result;
  149. if (expression instanceof Expressions.VariableLiteral) {
  150. result = [
  151. { instance: "expression", type: TYPES.VARIABLE, value: expression.id },
  152. ];
  153. } else if (expression instanceof Expressions.FunctionCall) {
  154. const funcObj = {
  155. instance: "expression",
  156. type: TYPES.FUNCTION,
  157. value: expression.id,
  158. };
  159. const paramsList = expression.actualParameters.map((e) =>
  160. expressionWalker(e)
  161. );
  162. //const params = Array.prototype.concat.apply([], paramsList);
  163. funcObj.params = paramsList;
  164. result = [funcObj];
  165. } else if (expression instanceof Expressions.UnaryApp) {
  166. const left = expressionWalker(expression.left);
  167. const opType = getOpType(expression.op);
  168. const opValue = translateOp(opType, expression.op);
  169. result = [{ instance: "operator", type: opType, value: opValue }, ...left];
  170. } else if (expression instanceof Expressions.InfixApp) {
  171. const left = expressionWalker(expression.left);
  172. const right = expressionWalker(expression.right);
  173. const opType = getOpType(expression.op);
  174. const opValue = translateOp(opType, expression.op);
  175. result = [
  176. ...left,
  177. { instance: "operator", type: opType, value: opValue },
  178. ...right,
  179. ];
  180. } else if (expression instanceof Expressions.ArrayAccess) {
  181. const line = expressionWalker(expression.line);
  182. let arrayClass = "vector";
  183. let column = null;
  184. if (expression.column) {
  185. arrayClass = "matrix";
  186. column = expressionWalker(expression.column);
  187. }
  188. result = [
  189. {
  190. instance: "expression",
  191. type: TYPES.VARIABLE,
  192. class: arrayClass,
  193. column: column,
  194. line: line,
  195. value: expression.id,
  196. },
  197. ];
  198. } else if (expression instanceof Expressions.BoolLiteral) {
  199. const value = expression.value;
  200. result = [
  201. {
  202. instance: "expression",
  203. class: "simple",
  204. type: TYPES.CONST,
  205. value: convertBoolToString(value),
  206. },
  207. ];
  208. } else {
  209. let value = expression.value;
  210. if (expression.value.toNumber) {
  211. if (
  212. Types.REAL.isCompatible(expression.type) &&
  213. expression.value.decimalPlaces() == 0
  214. ) {
  215. value = expression.value.toFixed(2);
  216. } else {
  217. value = expression.value.toNumber();
  218. }
  219. }
  220. result = [
  221. {
  222. instance: "expression",
  223. class: "simple",
  224. type: TYPES.CONST,
  225. value: value,
  226. },
  227. ];
  228. }
  229. if (expression.parenthesis) return ["(", ...result, ")"];
  230. else return result;
  231. }
  232. export function parseExpression (text) {
  233. const parser = IVProgParser.createParser(text);
  234. const expressionAST = parser.parseExpressionOR();
  235. return expressionWalker(expressionAST);
  236. }
  237. /**
  238. * @param {string} text
  239. * */
  240. export function parseCode (text) {
  241. const parser = IVProgParser.createParser(text, false);
  242. const codeLinesMap = new Map();
  243. const tokens = Array.from(parser.lexer.reset(text));
  244. const tokenStream = [];
  245. for (const token of tokens) {
  246. if (token.type === parser.ruleNames.ERROR) {
  247. return null;
  248. }
  249. if (token.type === parser.ruleNames.COMMENTS) {
  250. for (let i = 0; i <= token.lineBreaks; i++) {
  251. if (codeLinesMap.has(i + token.line))
  252. codeLinesMap.get(i + token.line).push(token);
  253. else codeLinesMap.set(i + token.line, [token]);
  254. }
  255. continue;
  256. }
  257. if (token.type !== parser.ruleNames.WHITESPACE) {
  258. tokenStream.push(token);
  259. }
  260. }
  261. parser.fill(tokenStream);
  262. const program = parser.parseTree();
  263. const globals = program.global.map((decl) =>
  264. variableDeclarationWalker(decl, true)
  265. );
  266. const functions = program.functions.map(functionWalker);
  267. return { globals, functions };
  268. }