From 9a018570c60f76aa0b47aff5883a83bf008bb25c Mon Sep 17 00:00:00 2001 From: Daniil ROSSO Date: Sat, 5 Feb 2022 17:28:01 +0100 Subject: [PATCH] Various fixes and comments --- src/scripts/output.js | 42 ++++++++++++--------- src/scripts/parser.js | 85 +++++++++++++++++++----------------------- src/scripts/process.js | 8 +++- 3 files changed, 69 insertions(+), 66 deletions(-) diff --git a/src/scripts/output.js b/src/scripts/output.js index 86f4b53..4eb89a0 100644 --- a/src/scripts/output.js +++ b/src/scripts/output.js @@ -10,11 +10,11 @@ let flag = false; // On file selection change: set to false /// Listen for user input $(document).ready(function () { $("*[id*=cb-]").attr("disabled", true); + /// Fill the modal-tutorial with text + fillModalToturial(); + /// Listen for clicks on "check all" $("#bt-check-all-cb").on("click", function () { - /// Fill the modal-tutorial with text - fillModalToturial("../../documents/CTL-tutorial.txt"); - /// Check if all checkboxes are in the same status of selection let bool; @@ -43,6 +43,7 @@ $(document).ready(function () { } }); + /// Listen for changes on the file dropdown $("#selectFile").on("change", function () { let selection = $("#selectFile").val(); @@ -56,12 +57,18 @@ $(document).ready(function () { atomicHandler(); flag = false; }); + + /// Listen for changes on atomic proposition dropdown $("*[id*=selectAP]").on("change", function () { updateAlgorithms(); }); + + /// Listen for changes on the algorithm checkbox $("#cb-algorithms").on("change", function () { atomicHandler(); }); + + /// Listen for clicks on the custom ctl button $("#custom-ctl-btn").on("click", function () { customCtlHandler(initial, states); }); @@ -111,7 +118,7 @@ $(document).ready(function () { }); }); -function fillModalToturial(filePath) { +function fillModalToturial() { /// Get content of a file and feed it to the modal // to avoid having too big of an HTML file @@ -124,9 +131,6 @@ function fillModalToturial(filePath) { // text = fs.readFileSync(filePath); text = fs.readFileSync("./documents/CTL-tutorial.html"); textByLine = text.toString().split("\r\n"); - - console.log("text : \n" + text); - console.log("textByLine : \n" + textByLine); } catch (err) { console.error("No document found for CTL tutorial : \n" + err); } @@ -269,6 +273,14 @@ function hideAllTitles() { $("#custom-ctl-output").attr("hidden", true); } +function updateAlgorithms() { + $('.algorithms:not(".title")').remove(); + let atom1 = $("#selectAP1").find(":selected").text(); + let atom2 = $("#selectAP2").find(":selected").text(); + base_algorithms = BaseAlgorithms(atom1, atom2); + displayAlgorithms(base_algorithms); +} + function atomicHandler() { $("#selectAP1").empty(); $("#selectAP2").empty(); @@ -302,14 +314,7 @@ function atomicHandler() { } } -function updateAlgorithms() { - $('.algorithms:not(".title")').remove(); - let atom1 = $("#selectAP1").find(":selected").text(); - let atom2 = $("#selectAP2").find(":selected").text(); - base_algorithms = BaseAlgorithms(atom1, atom2); - displayAlgorithms(base_algorithms); -} - +//Manages the custom ctl display by hiding and showing it function ctlHandler() { $("#custom-ctl").val(""); $("#selectFile").find(":selected").text() == "--Select a file" @@ -321,12 +326,13 @@ function ctlHandler() { $("#b-ctl-modal-tutorial").removeAttr("hidden")); } +//Manages the custom ctl logic function customCtlHandler(initial_states, states) { - let initial_state_position = states.indexOf(initial_states[0]); try { $("#custom-ctl-output").empty(); // Remove all child + //itterate through initial states for (let i in initial_states) { - let bool = CTLParser($("#custom-ctl").val().split(" ").join(""))[i]; + let bool = CTLParser($("#custom-ctl").val().split(" ").join(""))[i]; //purges whitespaces and returns the state truth let color; bool ? (color = "green") : (color = "red"); @@ -341,6 +347,6 @@ function customCtlHandler(initial_states, states) { ); } } catch (e) { - alert(e); + alert(e); //shows the user the reason the operation failes via errors thrown in the parser } } diff --git a/src/scripts/parser.js b/src/scripts/parser.js index 093facd..e51e7f9 100644 --- a/src/scripts/parser.js +++ b/src/scripts/parser.js @@ -1,28 +1,6 @@ -import { process } from "./process"; +import * as algo from "./algorithms"; import { display } from "./output"; -import { - not, - and, - or, - AX, - AU, - AF, - AG, - AT, - EX, - EU, - EF, - EG, - ET, -} from "./algorithms"; - -const filePath = "documents/test_files/"; - -// Display elements -export function output(fileName) { - let data = process(parse(fileName)); - display(data); -} + export function parse(fileName) { // Read document @@ -46,6 +24,7 @@ export function parse(fileName) { // Put content in table let textByLine = text.split("\r\n"); + textByLine.forEach(function callback(value, index, object) { if (value.match(/^S:|^L:|^T:|^I:|^CTL/)) { object.splice(index, 1); //removes indicators @@ -60,16 +39,15 @@ export function CTLParser(input) { let operator; let elements = []; + //regular expressions matching the different operators let reg_all = /!|&|\||A|E/; let reg_double = /&|\||AU|EU|AT|ET/; let reg_simple = /!|A|E/; let reg_AE = /X|G|F|U|T/; + //error flag to throw errors let flag = false; - console.log("input"); - console.log(input); - if (input.charAt(0).match(reg_all)) { input.charAt(input.length - 1) == ")" ? (input = input.slice(0, -1)) @@ -82,15 +60,17 @@ export function CTLParser(input) { input = input.split(/\((.+)/); operator = input[0]; input.pop(); + //input will be of format [operator,element1,element2 (if exists)] after processing + //at this point it is only [operator,elements] //handle an operation if (operator.match(reg_all)) { + //check if the operator needs a specific following one if (operator.match(/A|E/)) { - //handle A and E if (!input[1].charAt(0).match(reg_AE)) { throw "Please make sure that A and E are only applied on X G F U or T"; } else { - //change the operator to the composite form + //change the operator to its composite form operator = operator + input[1].charAt(0); input[1] = input[1].slice(2, -1); if ( @@ -99,20 +79,28 @@ export function CTLParser(input) { (operator == "AT") | (operator == "ET") ) { + //if the first element requires itself two elements, a left hand split must be done via first_splitter + //it will separate element 1 and element 2 disregarding complexity if (input[1].charAt(0).match(reg_all)) { elements = first_spliter(input); console.log(elements); elements[0] = CTLParser(elements[0]); } else { + //otherwise, the left hand element can easily be split by , elements = input[1].split(/,(.+)/); } } else if (input[1].charAt(0).match(reg_all)) { + //if the first element has an operator, it needs further processing + //we call recursively the ctl parser on the subfunction elements[0] = CTLParser(input[1]); } else { + //otherwise it will become element 1 elements[0] = input[1]; } } - } else if (input[1].charAt(0).match(reg_all)) { + } + //if the operator is not a composit function (A or E) + else if (input[1].charAt(0).match(reg_all)) { //element 1 is an operation elements = first_spliter(input); console.log("elements"); @@ -133,74 +121,78 @@ export function CTLParser(input) { } } } else { + //handles incorrect CTL structures throw "Not a valid operation, please check your ctl"; } + //control table for calling the correct algorithm switch (operator) { case "!": console.log("not is reached"); - result = not(elements[0]); + result = algo.not(elements[0]); break; case "&": console.log("and is reached"); - result = and(elements[0], elements[1]); + result = algo.and(elements[0], elements[1]); break; case "|": console.log("or is reached"); - result = or(elements[0], elements[1]); + result = algo.or(elements[0], elements[1]); break; case "AT": console.log("next is reached"); - result = AT(elements[0], elements[1]); + result = algo.AT(elements[0], elements[1]); break; case "AX": console.log("AX is reached"); - result = AX(elements[0]); + result = algo.AX(elements[0]); break; case "AU": console.log("AU is reached"); - result = AU(elements[0], elements[1]); + result = algo.AU(elements[0], elements[1]); break; case "AF": console.log("AF is reached"); - result = AF(elements[0]); + result = algo.AF(elements[0]); break; case "AG": console.log("AG is reached"); - result = AG(elements[0]); + result = algo.AG(elements[0]); break; case "EX": console.log("EX is reached"); - result = EX(elements[0]); + result = algo.EX(elements[0]); break; case "EU": console.log("EU is reached"); - result = EU(elements[0], elements[1]); + result = algo.EU(elements[0], elements[1]); break; case "EF": console.log("EF is reached"); - result = EF(elements[0]); + result = algo.EF(elements[0]); break; case "EG": console.log("EG is reached"); - result = EG(elements[0]); + result = algo.EG(elements[0]); break; case "ET": console.log("next is reached"); - result = ET(elements[0], elements[1]); + result = algo.ET(elements[0], elements[1]); break; default: + //this should never be thrown throw "Something went wrong (failed switch)"; } - Array.isArray(result) ? (result = result) : console.log("not an array"); - console.log("result: " + result); + return result; //return the table of truth } //splits the left hand element of a two elements operation +//input of format [operator,elements] function first_spliter(input) { - let para_counter = 1; + let para_counter = 1; //counter of open parenthesis let index; + //we start after the first operator and open parenthesis (so charAt(2)) for (let i = 2; i < input[1].length; i++) { if (input[1].charAt(i) == "(") para_counter++; if (input[1].charAt(i) == ")") para_counter--; @@ -212,6 +204,7 @@ function first_spliter(input) { return split_at_index(input[1], index); } +//handy function returning a string split in 2 at a specific index function split_at_index(value, index) { return [value.substring(0, index), value.substring(index + 1)]; } diff --git a/src/scripts/process.js b/src/scripts/process.js index 2fce123..ff469f7 100644 --- a/src/scripts/process.js +++ b/src/scripts/process.js @@ -1,29 +1,33 @@ export function process(input) { let states = input[0].replace(/{|}/g, "").split(","); - let tuples = input[1].replace(/\)|{|}/g, "").split("("); + tuples.filter(function (e) { return e; }); + tuples.forEach(function pairs(value, index, object) { object[index] = object[index].split(","); object[index] = object[index].filter(function (e) { return e; }); }); + tuples.shift(); let transitions = input[2].replace(/\),|\)|{|}/g, "").split("("); transitions.forEach(function pairs(value, index, object) { object[index] = object[index].split(","); }); + transitions.shift(); let initial_state = input[3].replace(/{|}/g, "").split(","); - + Array.isArray(initial_state) ? true : (initial_state = [initial_state]); let ctl = input[4]; + return { states: states, tuples: tuples,