|
@@ -1,3 +1,8 @@
|
|
|
+// iVProg - www.usp.br/line/ivprog
|
|
|
+// LInE - Free Education, Private Data
|
|
|
+
|
|
|
+// This is used when is loaded "ivph" file (under the button "upload" or GET)
|
|
|
+
|
|
|
import { IVProgParser } from "../ast/ivprogParser";
|
|
|
import * as Expressions from "../ast/expressions";
|
|
|
import { Types } from "../typeSystem/types";
|
|
@@ -13,7 +18,7 @@ const TYPES = {
|
|
|
RELATIONAL: "relational",
|
|
|
LOGIC: "logic",
|
|
|
ARITHMETIC: "arithmetic",
|
|
|
-};
|
|
|
+ };
|
|
|
|
|
|
function translateOp (type, op) {
|
|
|
switch (type) {
|
|
@@ -28,10 +33,10 @@ function translateOp (type, op) {
|
|
|
return "or";
|
|
|
} else {
|
|
|
return "not";
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-}
|
|
|
|
|
|
function getOpType (op) {
|
|
|
switch (op.ord) {
|
|
@@ -50,24 +55,24 @@ function getOpType (op) {
|
|
|
return TYPES.RELATIONAL;
|
|
|
default:
|
|
|
return TYPES.LOGIC;
|
|
|
+ }
|
|
|
}
|
|
|
-}
|
|
|
+
|
|
|
|
|
|
/**
|
|
|
* @param {Commands.Case} switchCase
|
|
|
* */
|
|
|
function switchCaseWalker (switchCase) {
|
|
|
const commands = switchCase.commands.map(commandWalker);
|
|
|
- const expression = switchCase.isDefault
|
|
|
- ? null
|
|
|
- : expressionWalker(switchCase.expression);
|
|
|
+ const expression = switchCase.isDefault ? null : expressionWalker(switchCase.expression);
|
|
|
return {
|
|
|
type: "switchcase",
|
|
|
line: switchCase.sourceInfo.line,
|
|
|
expression,
|
|
|
commands,
|
|
|
- };
|
|
|
-}
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
/**
|
|
|
* @param {Commands.Switch} switchCommand
|
|
@@ -79,8 +84,9 @@ function switchWalker (switchCommand) {
|
|
|
type: "switch",
|
|
|
expression,
|
|
|
cases,
|
|
|
- };
|
|
|
-}
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
/**
|
|
|
* @param {Commands.Return} returnCommand
|
|
@@ -89,16 +95,18 @@ function returnWalker (returnCommand) {
|
|
|
let expression = null;
|
|
|
if (returnCommand.expression !== null) {
|
|
|
expression = expressionWalker(returnCommand.expression);
|
|
|
- }
|
|
|
+ }
|
|
|
return {
|
|
|
type: "return",
|
|
|
expression,
|
|
|
- };
|
|
|
-}
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
function breakWalker (_) {
|
|
|
return { type: "break" };
|
|
|
-}
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
/**
|
|
|
* @param {Commands.For} forLoop
|
|
@@ -107,9 +115,7 @@ function forWalker (forLoop) {
|
|
|
const var_attribution = expressionWalker(forLoop.for_id);
|
|
|
const var_initial = expressionWalker(forLoop.for_from);
|
|
|
const condition = expressionWalker(forLoop.for_to);
|
|
|
- const step_expression = forLoop.for_pass
|
|
|
- ? expressionWalker(forLoop.for_pass)
|
|
|
- : [];
|
|
|
+ const step_expression = forLoop.for_pass ? expressionWalker(forLoop.for_pass) : [];
|
|
|
const commands = forLoop.commands.map(commandWalker);
|
|
|
return {
|
|
|
type: "repeatNtimes",
|
|
@@ -118,8 +124,8 @@ function forWalker (forLoop) {
|
|
|
condition,
|
|
|
step_expression,
|
|
|
commands,
|
|
|
- };
|
|
|
-}
|
|
|
+ };
|
|
|
+ }
|
|
|
|
|
|
/**
|
|
|
* @param {Commands.While} whileLoop
|
|
@@ -132,8 +138,9 @@ function whileWalker (whileLoop) {
|
|
|
type,
|
|
|
expression,
|
|
|
commands,
|
|
|
- };
|
|
|
-}
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
/**
|
|
|
* @param {Commands.IfThenElse} ifthenelse
|
|
@@ -148,16 +155,17 @@ function ifThenElseWalker (ifthenelse) {
|
|
|
ifFalse = ifthenelse.ifFalse.commands.map(commandWalker);
|
|
|
} else {
|
|
|
ifFalse = [ifThenElseWalker(ifthenelse.ifFalse)];
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
return {
|
|
|
type: "iftrue",
|
|
|
expression,
|
|
|
ifTrue,
|
|
|
ifFalse,
|
|
|
- };
|
|
|
+ };
|
|
|
}
|
|
|
|
|
|
+
|
|
|
/**
|
|
|
* @param {Commands.Assign} assingment
|
|
|
* */
|
|
@@ -170,29 +178,27 @@ function assignmentWalker (assingment) {
|
|
|
if (assingment.column) {
|
|
|
arrayClass = "matrix";
|
|
|
column = expressionWalker(assingment.column);
|
|
|
- }
|
|
|
- variable = [
|
|
|
- {
|
|
|
+ }
|
|
|
+ variable = [ {
|
|
|
instance: "expression",
|
|
|
type: TYPES.VARIABLE,
|
|
|
class: arrayClass,
|
|
|
column: column,
|
|
|
line: line,
|
|
|
value: assingment.id,
|
|
|
- },
|
|
|
- ];
|
|
|
+ },
|
|
|
+ ];
|
|
|
} else {
|
|
|
- variable = [
|
|
|
- { instance: "expression", type: TYPES.VARIABLE, value: assingment.id },
|
|
|
- ];
|
|
|
- }
|
|
|
+ variable = [ { instance: "expression", type: TYPES.VARIABLE, value: assingment.id }, ];
|
|
|
+ }
|
|
|
const expression = expressionWalker(assingment.expression);
|
|
|
return {
|
|
|
type: "attribution",
|
|
|
variable,
|
|
|
expression,
|
|
|
- };
|
|
|
-}
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
/**
|
|
|
* @param {Command} command
|
|
@@ -217,10 +223,11 @@ function commandWalker (command) {
|
|
|
parsedCommand = forWalker(command);
|
|
|
} else {
|
|
|
throw new Error("not implemented");
|
|
|
- }
|
|
|
+ }
|
|
|
parsedCommand.line = command.sourceInfo.line;
|
|
|
return parsedCommand;
|
|
|
-}
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
/**
|
|
|
* @param {Commands.FunctionCall} functionCall
|
|
@@ -229,33 +236,33 @@ function functionCallWalker (functionCall) {
|
|
|
let name = functionCall.id;
|
|
|
if (name.indexOf(".") !== -1) {
|
|
|
name = name.split(".")[1];
|
|
|
- }
|
|
|
+ }
|
|
|
const parameters = functionCall.actualParameters.map(expressionWalker);
|
|
|
if (name === "$write") {
|
|
|
const lastInput = parameters[parameters.length - 1][0];
|
|
|
// if lastInput is an object with value === '\n', newLine is true
|
|
|
const newLine = lastInput.value && lastInput.value.match(/^\n$/) !== null;
|
|
|
- const content = newLine
|
|
|
- ? parameters.slice(0, parameters.length - 1)
|
|
|
- : parameters;
|
|
|
+ const content = newLine ? parameters.slice(0, parameters.length - 1) : parameters;
|
|
|
return {
|
|
|
type: "writer",
|
|
|
newLine,
|
|
|
content,
|
|
|
- };
|
|
|
- }
|
|
|
+ };
|
|
|
+ }
|
|
|
if (name === "$read") {
|
|
|
return {
|
|
|
type: "reader",
|
|
|
variable: parameters[0],
|
|
|
- };
|
|
|
- }
|
|
|
+ };
|
|
|
+ }
|
|
|
return {
|
|
|
type: "functioncall",
|
|
|
parameters_list: parameters,
|
|
|
name: functionCall.id,
|
|
|
- };
|
|
|
-}
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
/**
|
|
|
* @param {Commands.Function} func
|
|
|
* */
|
|
@@ -268,22 +275,19 @@ function functionWalker (func) {
|
|
|
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
|
|
|
- );
|
|
|
+ }
|
|
|
+ funcDeclaration.parameters_list = func.formalParameters.map(functionParameterWalker);
|
|
|
+ funcDeclaration.variables_list = func.variablesDeclarations.map(variableDeclarationWalker);
|
|
|
funcDeclaration.commands = func.commands.map(commandWalker);
|
|
|
return funcDeclaration;
|
|
|
-}
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
/**
|
|
|
* @param {Commands.FormalParameter} formalParameter
|
|
@@ -299,15 +303,16 @@ function functionParameterWalker (formalParameter) {
|
|
|
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
|
|
@@ -323,7 +328,7 @@ function variableDeclarationWalker (command, global = false) {
|
|
|
dimension: 0,
|
|
|
value: 0,
|
|
|
is_const: false,
|
|
|
- };
|
|
|
+ };
|
|
|
variable.is_const = global && command.isConst;
|
|
|
if (command instanceof Commands.ArrayDeclaration) {
|
|
|
// array
|
|
@@ -332,31 +337,26 @@ 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 {
|
|
|
// atomic
|
|
|
variable.type = command.type.value;
|
|
|
variable.value = variableInitialWalker(command.initial);
|
|
|
- }
|
|
|
+ }
|
|
|
return variable;
|
|
|
-}
|
|
|
+ }
|
|
|
|
|
|
-/**
|
|
|
- * @param {any} expression
|
|
|
- * */
|
|
|
+
|
|
|
+/// @param {any} expression
|
|
|
function variableInitialWalker (expression) {
|
|
|
if (expression instanceof Expressions.UnaryApp) {
|
|
|
const left = variableInitialWalker(expression.left);
|
|
@@ -373,39 +373,32 @@ function variableInitialWalker (expression) {
|
|
|
} else if (expression instanceof Literal) {
|
|
|
let value = expression.value;
|
|
|
if (expression.value.toNumber) {
|
|
|
- if (
|
|
|
- Types.REAL.isCompatible(expression.type) &&
|
|
|
- expression.value.decimalPlaces() == 0
|
|
|
- ) {
|
|
|
+ if (Types.REAL.isCompatible(expression.type) && expression.value.decimalPlaces() == 0) {
|
|
|
value = Number(expression.value.toFixed(2));
|
|
|
} else {
|
|
|
value = expression.value.toNumber();
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
return value;
|
|
|
- }
|
|
|
+ }
|
|
|
throw new Error("invalid variable initial value: " + expression.toString());
|
|
|
-}
|
|
|
+ }
|
|
|
|
|
|
-/**
|
|
|
- *
|
|
|
- * @return {[]}
|
|
|
- **/
|
|
|
+
|
|
|
+/// @return {[]}
|
|
|
function expressionWalker (expression) {
|
|
|
let result;
|
|
|
if (expression instanceof Expressions.VariableLiteral) {
|
|
|
- result = [
|
|
|
- { instance: "expression", type: TYPES.VARIABLE, value: expression.id },
|
|
|
- ];
|
|
|
+ result = [ { instance: "expression", type: TYPES.VARIABLE, value: expression.id }, ];
|
|
|
} else if (expression instanceof Expressions.FunctionCall) {
|
|
|
const funcObj = {
|
|
|
instance: "expression",
|
|
|
type: TYPES.FUNCTION,
|
|
|
value: expression.id,
|
|
|
- };
|
|
|
+ };
|
|
|
const paramsList = expression.actualParameters.map((e) =>
|
|
|
expressionWalker(e)
|
|
|
- );
|
|
|
+ );
|
|
|
//const params = Array.prototype.concat.apply([], paramsList);
|
|
|
funcObj.params = paramsList;
|
|
|
result = [funcObj];
|
|
@@ -423,7 +416,7 @@ function expressionWalker (expression) {
|
|
|
...left,
|
|
|
{ instance: "operator", type: opType, value: opValue },
|
|
|
...right,
|
|
|
- ];
|
|
|
+ ];
|
|
|
} else if (expression instanceof Expressions.ArrayAccess) {
|
|
|
const line = expressionWalker(expression.line);
|
|
|
let arrayClass = "vector";
|
|
@@ -431,27 +424,25 @@ function expressionWalker (expression) {
|
|
|
if (expression.column) {
|
|
|
arrayClass = "matrix";
|
|
|
column = expressionWalker(expression.column);
|
|
|
- }
|
|
|
- result = [
|
|
|
- {
|
|
|
+ }
|
|
|
+ result = [ {
|
|
|
instance: "expression",
|
|
|
type: TYPES.VARIABLE,
|
|
|
class: arrayClass,
|
|
|
column: column,
|
|
|
line: line,
|
|
|
value: expression.id,
|
|
|
- },
|
|
|
- ];
|
|
|
+ },
|
|
|
+ ];
|
|
|
} else if (expression instanceof Expressions.BoolLiteral) {
|
|
|
const value = expression.value;
|
|
|
- result = [
|
|
|
- {
|
|
|
+ result = [ {
|
|
|
instance: "expression",
|
|
|
class: "simple",
|
|
|
type: TYPES.CONST,
|
|
|
value: convertBoolToString(value),
|
|
|
- },
|
|
|
- ];
|
|
|
+ },
|
|
|
+ ];
|
|
|
} else {
|
|
|
let value = expression.value;
|
|
|
if (expression.value.toNumber) {
|
|
@@ -462,31 +453,34 @@ function expressionWalker (expression) {
|
|
|
value = Number(expression.value.toFixed(2));
|
|
|
} else {
|
|
|
value = expression.value.toNumber();
|
|
|
+ }
|
|
|
}
|
|
|
+ result = [ { instance: "expression", class: "simple", type: TYPES.CONST, value: value, }, ];
|
|
|
}
|
|
|
- result = [
|
|
|
- {
|
|
|
- instance: "expression",
|
|
|
- class: "simple",
|
|
|
- type: TYPES.CONST,
|
|
|
- value: value,
|
|
|
- },
|
|
|
- ];
|
|
|
- }
|
|
|
if (expression.parenthesis) return ["(", ...result, ")"];
|
|
|
else return result;
|
|
|
-}
|
|
|
+ }
|
|
|
|
|
|
export function parseExpression (text) {
|
|
|
const parser = IVProgParser.createParser(text);
|
|
|
const expressionAST = parser.parseExpressionOR();
|
|
|
return expressionWalker(expressionAST);
|
|
|
-}
|
|
|
+ }
|
|
|
|
|
|
-/**
|
|
|
- * @param {string} text
|
|
|
- * */
|
|
|
+
|
|
|
+/// @param {string} text
|
|
|
+/// @calledby js/util/iassignHelpers.js!setPreviousAlgorithm(code)
|
|
|
export function parseCode (text) {
|
|
|
+ console.log("js/util/parseFromVisual.js!parseCode(text): can this function be removed? If is it appearing in log, then no...");
|
|
|
+ //D console.trace();
|
|
|
+ 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();
|
|
|
const parser = IVProgParser.createParser(text, false);
|
|
|
const codeLinesMap = new Map();
|
|
|
const tokens = Array.from(parser.lexer.reset(text));
|
|
@@ -494,29 +488,63 @@ export function parseCode (text) {
|
|
|
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);
|
|
|
try {
|
|
|
const program = parser.parseTree();
|
|
|
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 astFunctions = program.functions;
|
|
|
+ functions.forEach((visualFunc, index) => {
|
|
|
+ const astFunc = astFunctions[index];
|
|
|
+ const funcStartLine = astFunc.sourceInfo.line;
|
|
|
+ let funcEndLine;
|
|
|
+ if (astFunctions[index + 1]) {
|
|
|
+ funcEndLine = astFunctions[index + 1].sourceInfo.line;
|
|
|
+ } else {
|
|
|
+ funcEndLine = Infinity;
|
|
|
+ }
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ //Gleyce end: new code to read IVPH file with comment (//)
|
|
|
+
|
|
|
return { globals, functions };
|
|
|
} catch (e) {
|
|
|
console.error(e);
|
|
|
return null;
|
|
|
- }
|
|
|
-}
|
|
|
+ }
|
|
|
+ }
|