|
|
@@ -163,7 +163,7 @@ function ifThenElseWalker (ifthenelse) {
|
|
|
ifTrue,
|
|
|
ifFalse,
|
|
|
};
|
|
|
-}
|
|
|
+ }
|
|
|
|
|
|
|
|
|
/**
|
|
|
@@ -337,14 +337,14 @@ function variableDeclarationWalker (command, global = false) {
|
|
|
if (command.isVector) {
|
|
|
variable.columns = lines.value;
|
|
|
variable.dimension = 1;
|
|
|
- const values = command.initial.value.map((exp) => variableInitialWalker(exp) );
|
|
|
+ const values = command.initial.value.map((exp) => variableInitialWalker(exp));
|
|
|
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.value.map((rows) => rows.value.map((exp) => variableInitialWalker(exp)) );
|
|
|
+ const values = command.initial.value.map((rows) => rows.value.map((exp) => variableInitialWalker(exp)));
|
|
|
variable.value = values;
|
|
|
}
|
|
|
} else {
|
|
|
@@ -362,10 +362,8 @@ function variableInitialWalker (expression) {
|
|
|
const left = variableInitialWalker(expression.left);
|
|
|
const opType = getOpType(expression.op);
|
|
|
if (opType !== TYPES.ARITHMETIC) {
|
|
|
- throw new Error(
|
|
|
- "invalid variable initial value: " + expression.toString()
|
|
|
- );
|
|
|
- }
|
|
|
+ throw new Error("invalid variable initial value: " + expression.toString());
|
|
|
+ }
|
|
|
return `${expression.op.value}${left}`;
|
|
|
} else if (expression instanceof Expressions.BoolLiteral) {
|
|
|
const value = expression.value;
|
|
|
@@ -396,10 +394,7 @@ function expressionWalker (expression) {
|
|
|
type: TYPES.FUNCTION,
|
|
|
value: expression.id,
|
|
|
};
|
|
|
- const paramsList = expression.actualParameters.map((e) =>
|
|
|
- expressionWalker(e)
|
|
|
- );
|
|
|
- //const params = Array.prototype.concat.apply([], paramsList);
|
|
|
+ const paramsList = expression.actualParameters.map((e) => expressionWalker(e));
|
|
|
funcObj.params = paramsList;
|
|
|
result = [funcObj];
|
|
|
} else if (expression instanceof Expressions.UnaryApp) {
|
|
|
@@ -445,16 +440,19 @@ function expressionWalker (expression) {
|
|
|
];
|
|
|
} else {
|
|
|
let value = expression.value;
|
|
|
- if (expression.value.toNumber) {
|
|
|
- if (
|
|
|
- Types.REAL.isCompatible(expression.type) &&
|
|
|
- expression.value.decimalPlaces() == 0
|
|
|
- ) {
|
|
|
- value = Number(expression.value.toFixed(2));
|
|
|
+
|
|
|
+ //x if (expression.value.toNumber)
|
|
|
+ if (value !== null && value !== undefined && typeof value.toNumber === "function") {
|
|
|
+ //x if (Types.REAL.isCompatible(expression.type) && expression.value.decimalPlaces() == 0)
|
|
|
+ if (Types.REAL.isCompatible(expression.type) && value.decimalPlaces() == 0) {
|
|
|
+ //x value = Number(expression.value.toFixed(2));
|
|
|
+ value = Number(value.toFixed(2));
|
|
|
} else {
|
|
|
- value = expression.value.toNumber();
|
|
|
+ //x value = expression.value.toNumber();
|
|
|
+ value = value.toNumber();
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
result = [ { instance: "expression", class: "simple", type: TYPES.CONST, value: value, }, ];
|
|
|
}
|
|
|
if (expression.parenthesis) return ["(", ...result, ")"];
|
|
|
@@ -476,11 +474,12 @@ export function parseCode (text) {
|
|
|
return parserCodeVisual(text);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
/// @param {string} text
|
|
|
/// @calledby js/util/iassignHelpers.js!setPreviousAlgorithm(code)
|
|
|
-export function parserCodeVisual (text) { // Gleyce
|
|
|
- console.log("js/util/parseFromVisual.js!parserCodeVisual(text): starting");
|
|
|
- //D console.trace();
|
|
|
+export function parserCodeVisual (text) { // Gleyce; Edilson
|
|
|
+ console.log("js/util/parseFromVisual.js!parserCodeVisual(text): starting"); //D console.trace();
|
|
|
+
|
|
|
const parser = IVProgParser.createParser(text, false);
|
|
|
const codeLinesMap = new Map();
|
|
|
const tokens = Array.from(parser.lexer.reset(text));
|
|
|
@@ -504,21 +503,15 @@ export function parserCodeVisual (text) { // Gleyce
|
|
|
parser.fill(tokenStream);
|
|
|
try {
|
|
|
const program = parser.parseTree();
|
|
|
- const globals = program.global.map((decl) =>
|
|
|
- variableDeclarationWalker(decl, true)
|
|
|
- );
|
|
|
+ const globals = program.global.map((decl) => variableDeclarationWalker(decl, true));
|
|
|
const functions = program.functions.map(functionWalker);
|
|
|
|
|
|
//Gleyce start: new code to read IVPH file with comment (//)
|
|
|
const allComments = [];
|
|
|
for (const [line, commentTokens] of codeLinesMap.entries()) {
|
|
|
for (const token of commentTokens) {
|
|
|
- const commentText = token.text.replace(/^\/\//, '').trim();
|
|
|
- allComments.push({
|
|
|
- type: "comment",
|
|
|
- comment_text: commentText,
|
|
|
- line: token.line,
|
|
|
- });
|
|
|
+ const commentText = token.text.replace(/^\/\//, "").trim();
|
|
|
+ allComments.push({ type: "comment", comment_text: commentText, line: token.line, });
|
|
|
}
|
|
|
}
|
|
|
const astFunctions = program.functions;
|
|
|
@@ -531,13 +524,29 @@ export function parserCodeVisual (text) { // Gleyce
|
|
|
} else {
|
|
|
funcEndLine = Infinity;
|
|
|
}
|
|
|
- const funcComments = allComments.filter(comment =>
|
|
|
- comment.line > funcStartLine && comment.line < funcEndLine
|
|
|
- );
|
|
|
+
|
|
|
+ const funcComments = allComments.filter((comment) => comment.line > funcStartLine && comment.line < funcEndLine);
|
|
|
+
|
|
|
if (funcComments.length > 0) {
|
|
|
- const allCommands = [...visualFunc.commands, ...funcComments];
|
|
|
- allCommands.sort((a, b) => a.line - b.line);
|
|
|
- visualFunc.commands = allCommands;
|
|
|
+ let firstCommandLine = Infinity;
|
|
|
+ if (visualFunc.commands.length > 0) {
|
|
|
+ firstCommandLine = visualFunc.commands[0].line;
|
|
|
+ }
|
|
|
+
|
|
|
+ const commentsForVariables = funcComments.filter((c) => c.line < firstCommandLine);
|
|
|
+
|
|
|
+ if (commentsForVariables.length > 0) {
|
|
|
+ const allVariables = [ ...visualFunc.variables_list, ...commentsForVariables, ];
|
|
|
+ allVariables.sort((a, b) => a.line - b.line);
|
|
|
+ visualFunc.variables_list = allVariables;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (visualFunc.commands.length > 0) {
|
|
|
+ const lastCommandLine = visualFunc.commands[visualFunc.commands.length - 1]?.line || funcEndLine;
|
|
|
+ const commentsForCommands = funcComments.filter((c) => c.line >= firstCommandLine);
|
|
|
+
|
|
|
+ visualFunc.commands = associateCommentsToCommands(visualFunc.commands, commentsForCommands, firstCommandLine - 1, lastCommandLine + 100);
|
|
|
+ }
|
|
|
}
|
|
|
});
|
|
|
//Gleyce end: new code to read IVPH file with comment (//)
|
|
|
@@ -547,4 +556,186 @@ export function parserCodeVisual (text) { // Gleyce
|
|
|
console.error(e);
|
|
|
return null;
|
|
|
}
|
|
|
- }
|
|
|
+ } // export function parserCodeVisual(text)
|
|
|
+
|
|
|
+
|
|
|
+//comments starts (Edilson)
|
|
|
+
|
|
|
+function associateCommentsToCommands (commands, allComments, startLine, endLine) {
|
|
|
+ const scopeComments = allComments.filter((c) => c.line > startLine && c.line < endLine);
|
|
|
+
|
|
|
+ if (scopeComments.length === 0) return commands;
|
|
|
+
|
|
|
+ const processedCommands = commands.map((cmd) => {
|
|
|
+ if (cmd.type === "comment") return cmd;
|
|
|
+
|
|
|
+ const processedCmd = { ...cmd };
|
|
|
+
|
|
|
+ if (cmd.type === "iftrue") {
|
|
|
+ if (cmd.ifTrue && cmd.ifTrue.length > 0) {
|
|
|
+ const ifBlock = cmd.ifTrue;
|
|
|
+ const blockStart = cmd.line;
|
|
|
+ const blockEnd = ifBlock[ifBlock.length - 1]?.line || cmd.line;
|
|
|
+ processedCmd.ifTrue = associateCommentsToCommands(ifBlock, allComments, blockStart, blockEnd);
|
|
|
+ }
|
|
|
+ if (cmd.ifFalse && cmd.ifFalse.length > 0) {
|
|
|
+ const elseBlock = cmd.ifFalse;
|
|
|
+ const blockStart = cmd.ifTrue && cmd.ifTrue.length > 0 ? cmd.ifTrue[cmd.ifTrue.length - 1]?.line || cmd.line : cmd.line;
|
|
|
+ const blockEnd = elseBlock[elseBlock.length - 1]?.line || blockStart;
|
|
|
+ processedCmd.ifFalse = associateCommentsToCommands(elseBlock, allComments, blockStart, blockEnd);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (cmd.type === "whiletrue" || cmd.type === "dowhiletrue") {
|
|
|
+ if (cmd.commands && cmd.commands.length > 0) {
|
|
|
+ const blockStart = cmd.line;
|
|
|
+ const blockEnd = cmd.commands[cmd.commands.length - 1]?.line || cmd.line;
|
|
|
+ processedCmd.commands = associateCommentsToCommands(cmd.commands, allComments, blockStart, blockEnd);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (cmd.type === "repeatNtimes") {
|
|
|
+ if (cmd.commands && cmd.commands.length > 0) {
|
|
|
+ const blockStart = cmd.line;
|
|
|
+ const blockEnd = cmd.commands[cmd.commands.length - 1]?.line || cmd.line;
|
|
|
+ processedCmd.commands = associateCommentsToCommands(cmd.commands, allComments, blockStart, blockEnd);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (cmd.type === "switch") {
|
|
|
+ if (cmd.cases) {
|
|
|
+ processedCmd.cases = cmd.cases.map((caseObj) => {
|
|
|
+ if (caseObj.commands && caseObj.commands.length > 0) {
|
|
|
+ const blockStart = caseObj.line || cmd.line;
|
|
|
+ const blockEnd = caseObj.commands[caseObj.commands.length - 1]?.line || blockStart;
|
|
|
+ return {
|
|
|
+ ...caseObj,
|
|
|
+ commands: associateCommentsToCommands(caseObj.commands, allComments, blockStart, blockEnd),
|
|
|
+ };
|
|
|
+ }
|
|
|
+ return caseObj;
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return processedCmd;
|
|
|
+ });
|
|
|
+
|
|
|
+ const usedCommentLines = new Set();
|
|
|
+
|
|
|
+ function collectUsedComments (cmdList) {
|
|
|
+ cmdList.forEach((cmd) => {
|
|
|
+ if (cmd.type === "comment") {
|
|
|
+ usedCommentLines.add(cmd.line);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (cmd.type === "iftrue") {
|
|
|
+ if (cmd.ifTrue) collectUsedComments(cmd.ifTrue);
|
|
|
+ if (cmd.ifFalse) collectUsedComments(cmd.ifFalse);
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((cmd.type === "whiletrue" || cmd.type === "dowhiletrue" || cmd.type === "repeatNtimes") && cmd.commands) {
|
|
|
+ collectUsedComments(cmd.commands);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (cmd.type === "switch" && cmd.cases) {
|
|
|
+ cmd.cases.forEach((c) => {
|
|
|
+ if (c.commands) collectUsedComments(c.commands);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ collectUsedComments(processedCommands);
|
|
|
+
|
|
|
+ const availableComments = scopeComments.filter((c) => !usedCommentLines.has(c.line));
|
|
|
+
|
|
|
+ const merged = [...processedCommands, ...availableComments].sort((a, b) => a.line - b.line);
|
|
|
+
|
|
|
+ return associateInlineComments(merged, allComments);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+function associateInlineComments (commands, allComments) {
|
|
|
+ if (!allComments || allComments.length === 0) return commands;
|
|
|
+
|
|
|
+ const commentsByLine = new Map();
|
|
|
+ allComments.forEach((comment) => {
|
|
|
+ if (!commentsByLine.has(comment.line)) {
|
|
|
+ commentsByLine.set(comment.line, []);
|
|
|
+ }
|
|
|
+ commentsByLine.get(comment.line).push(comment);
|
|
|
+ });
|
|
|
+
|
|
|
+ const inlineCommentLines = new Set();
|
|
|
+
|
|
|
+ function processCommands (cmdList) {
|
|
|
+ return cmdList.map((cmd) => {
|
|
|
+ if (cmd.type === "comment") return cmd;
|
|
|
+
|
|
|
+ const processedCmd = { ...cmd };
|
|
|
+
|
|
|
+ if (cmd.line && commentsByLine.has(cmd.line)) {
|
|
|
+ const commentsOnLine = commentsByLine.get(cmd.line);
|
|
|
+
|
|
|
+ const availableComment = commentsOnLine.find((c) => !inlineCommentLines.has(c.line));
|
|
|
+
|
|
|
+ if (availableComment) {
|
|
|
+ processedCmd.inlineComment = availableComment.comment_text;
|
|
|
+ inlineCommentLines.add(cmd.line);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (cmd.type === "iftrue") {
|
|
|
+ if (cmd.ifTrue) processedCmd.ifTrue = processCommands(cmd.ifTrue);
|
|
|
+ if (cmd.ifFalse) processedCmd.ifFalse = processCommands(cmd.ifFalse);
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((cmd.type === "whiletrue" || cmd.type === "dowhiletrue" || cmd.type === "repeatNtimes") && cmd.commands) {
|
|
|
+ processedCmd.commands = processCommands(cmd.commands);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (cmd.type === "switch" && cmd.cases) {
|
|
|
+ processedCmd.cases = cmd.cases.map((caseObj) => ({
|
|
|
+ ...caseObj,
|
|
|
+ commands: caseObj.commands ? processCommands(caseObj.commands) : [],
|
|
|
+ }));
|
|
|
+ }
|
|
|
+
|
|
|
+ return processedCmd;
|
|
|
+ });
|
|
|
+ } // function processCommands(cmdList)
|
|
|
+
|
|
|
+ const processedCommands = processCommands(commands);
|
|
|
+
|
|
|
+ function filterInlineComments (cmdList) {
|
|
|
+ return cmdList.filter((cmd) => {
|
|
|
+ if (cmd.type === "comment" && inlineCommentLines.has(cmd.line)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (cmd.type === "iftrue") {
|
|
|
+ if (cmd.ifTrue) cmd.ifTrue = filterInlineComments(cmd.ifTrue);
|
|
|
+ if (cmd.ifFalse) cmd.ifFalse = filterInlineComments(cmd.ifFalse);
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((cmd.type === "whiletrue" || cmd.type === "dowhiletrue" || cmd.type === "repeatNtimes") && cmd.commands) {
|
|
|
+ cmd.commands = filterInlineComments(cmd.commands);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (cmd.type === "switch" && cmd.cases) {
|
|
|
+ cmd.cases = cmd.cases.map((caseObj) => ({
|
|
|
+ ...caseObj,
|
|
|
+ commands: caseObj.commands ? filterInlineComments(caseObj.commands) : [],
|
|
|
+ }));
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ return filterInlineComments(processedCommands);
|
|
|
+ } // function associateInlineComments(commands, allComments)
|
|
|
+
|
|
|
+//comments end (Edilson)
|