|
@@ -2,6 +2,8 @@ import { IVProgParser } from "../ast/ivprogParser";
|
|
|
import * as Expressions from "../ast/expressions";
|
|
|
import { Types } from "../typeSystem/types";
|
|
|
import { convertBoolToString } from "../typeSystem/parsers";
|
|
|
+import * as Commands from "../ast/commands";
|
|
|
+import { ArrayType } from "../typeSystem/array_type";
|
|
|
|
|
|
const TYPES = {
|
|
|
VARIABLE: "var",
|
|
@@ -49,7 +51,105 @@ function getOpType (op) {
|
|
|
return TYPES.LOGIC;
|
|
|
}
|
|
|
}
|
|
|
+/**
|
|
|
+ * @param {Commands.Function} func
|
|
|
+ * */
|
|
|
+function functionWalker (func) {
|
|
|
+ const funcDeclaration = {
|
|
|
+ name: func.name,
|
|
|
+ return_type: "",
|
|
|
+ return_dimensions: 0,
|
|
|
+ parameters_list: [],
|
|
|
+ variables_list: [],
|
|
|
+ commands: [],
|
|
|
+ };
|
|
|
+ if (func.returnType instanceof ArrayType) {
|
|
|
+ funcDeclaration.return_type = func.returnType.innerType.value;
|
|
|
+ funcDeclaration.return_dimensions = func.returnType.dimensions;
|
|
|
+ } else {
|
|
|
+ funcDeclaration.return_type = func.returnType.value;
|
|
|
+ }
|
|
|
+ funcDeclaration.parameters_list = func.formalParameters.map(
|
|
|
+ functionParameterWalker
|
|
|
+ );
|
|
|
+ funcDeclaration.variables_list = func.variablesDeclarations.map(
|
|
|
+ variableDeclarationWalker
|
|
|
+ );
|
|
|
+ return funcDeclaration;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @param {Commands.FormalParameter} formalParameter
|
|
|
+ * */
|
|
|
+function functionParameterWalker (formalParameter) {
|
|
|
+ const variable = {
|
|
|
+ name: formalParameter.id,
|
|
|
+ type: "",
|
|
|
+ rows: 0,
|
|
|
+ columns: 0,
|
|
|
+ dimension: 0,
|
|
|
+ value: 0,
|
|
|
+ is_const: false,
|
|
|
+ reference: formalParameter.byRef,
|
|
|
+ };
|
|
|
+ if (formalParameter.type instanceof ArrayType) {
|
|
|
+ variable.type = formalParameter.type.innerType.value;
|
|
|
+ variable.dimension = formalParameter.type.dimensions;
|
|
|
+ } else {
|
|
|
+ variable.type = formalParameter.type.value;
|
|
|
+ }
|
|
|
+ return variable;
|
|
|
+}
|
|
|
|
|
|
+/**
|
|
|
+ * @param {Commands.Declaration} command
|
|
|
+ * @param {boolean} global
|
|
|
+ * */
|
|
|
+function variableDeclarationWalker (command, global = false) {
|
|
|
+ const variable = {
|
|
|
+ name: command.id,
|
|
|
+ type: "",
|
|
|
+ rows: 0,
|
|
|
+ columns: 0,
|
|
|
+ dimension: 0,
|
|
|
+ value: 0,
|
|
|
+ is_const: false,
|
|
|
+ };
|
|
|
+ variable.is_const = global && command.isConst;
|
|
|
+ if (command instanceof Commands.ArrayDeclaration) {
|
|
|
+ // array
|
|
|
+ const lines = expressionWalker(command.lines).pop();
|
|
|
+ variable.type = command.type.innerType.value;
|
|
|
+ if (command.isVector) {
|
|
|
+ variable.rows = 1;
|
|
|
+ variable.columns = lines.value;
|
|
|
+ variable.dimension = 1;
|
|
|
+ const values = command.initial.map(
|
|
|
+ (exp) => expressionWalker(exp).pop().value
|
|
|
+ );
|
|
|
+ variable.value = values;
|
|
|
+ } else {
|
|
|
+ const columns = expressionWalker(command.columns).pop();
|
|
|
+ variable.dimension = 2;
|
|
|
+ variable.rows = lines.value;
|
|
|
+ variable.columns = columns.value;
|
|
|
+ const values = command.initial.map((rows) =>
|
|
|
+ rows.map((exp) => expressionWalker(exp).pop().value)
|
|
|
+ );
|
|
|
+ variable.value = values;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // atomic
|
|
|
+ variable.type = command.type.value;
|
|
|
+ variable.value = expressionWalker(command.initial).pop().value;
|
|
|
+ }
|
|
|
+ return variable;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ *
|
|
|
+ * @return {[]}
|
|
|
+ **/
|
|
|
function expressionWalker (expression) {
|
|
|
let result;
|
|
|
if (expression instanceof Expressions.VariableLiteral) {
|
|
@@ -141,3 +241,36 @@ export function parseExpression (text) {
|
|
|
const expressionAST = parser.parseExpressionOR();
|
|
|
return expressionWalker(expressionAST);
|
|
|
}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @param {string} text
|
|
|
+ * */
|
|
|
+export function parseCode (text) {
|
|
|
+ const parser = IVProgParser.createParser(text, false);
|
|
|
+ const codeLinesMap = new Map();
|
|
|
+ const tokens = Array.from(parser.lexer.reset(text));
|
|
|
+ const tokenStream = [];
|
|
|
+ for (const token of tokens) {
|
|
|
+ if (token.type === parser.ruleNames.ERROR) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ if (token.type === parser.ruleNames.COMMENTS) {
|
|
|
+ for (let i = 0; i <= token.lineBreaks; i++) {
|
|
|
+ if (codeLinesMap.has(i + token.line))
|
|
|
+ codeLinesMap.get(i + token.line).push(token);
|
|
|
+ else codeLinesMap.set(i + token.line, [token]);
|
|
|
+ }
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (token.type !== parser.ruleNames.WHITESPACE) {
|
|
|
+ tokenStream.push(token);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ parser.fill(tokenStream);
|
|
|
+ const program = parser.parseTree();
|
|
|
+ const globals = program.global.map((decl) =>
|
|
|
+ variableDeclarationWalker(decl, true)
|
|
|
+ );
|
|
|
+ const functions = program.functions.map(functionWalker);
|
|
|
+ return { globals, functions };
|
|
|
+}
|