UNPKG

algomin

Version:

Algomin - Viszualizing Distributed Algorithms

126 lines (104 loc) 4.11 kB
export class Parser { /** * Parses an Algomin animation code by splitting and checking * each line if a regex matches the given command. Then it filters out * the paramters and pushes it as a JSON object to the return list. * @param expression_string Expression String of Algomin Code * @returns {*[]} */ parseExpression(expression_string) { let instructions = []; const lines = expression_string.split('\n'); const objectRegex = /^(\w+)\s*=\s*shape\(([^)]+)\)$/i; const sendMessageRegex = /^(\w+)\.sendMessage\(([^)]+)\)$/i; const waitRegex = /wait\(duration=(\d+)\)/; const killRegex = /([a-zA-Z_$][a-zA-Z0-9_$]*)\.kill\(\)/; for (const [i, line] of lines.entries()) { if (line.trim() === "") { continue; } if (objectRegex.exec(line)) { const id = line.split(" ").join("").split("=")[0]; instructions.push({id: id, type: "SHAPE", args: this.parseArgs(line)}); } else if (sendMessageRegex.exec(line)) { const source = line.split(".")[0]; instructions.push({source: source, type: "SEND", args: this.parseArgs(line)}); } else if (waitRegex.exec(line)) { instructions.push({source: null, type: "WAIT", args: this.parseArgs(line)}); } else if (killRegex.exec(line)) { const source = line.split(".")[0]; instructions.push({source: source, type: "KILL", args: this.parseArgs(line)}); } else { throw new Error(`Unrecognized line at ${i+1}: ${line}`); } } return instructions; } /** * Splits all arguments it finds in a line and returns a JSON of all parameters * @param line String * @returns {{}} */ parseArgs(line) { let first_bracket_index = -1; let last_bracket_index = -1; for (let i = 0; i < line.length; i++) { if (line[i] === "(" && first_bracket_index < 0) { first_bracket_index = i; } else if (line[i] === ")") { last_bracket_index = i; } } let new_line = line.substring(first_bracket_index + 1, last_bracket_index + 1) let inside_quote = false; let last_index = 0; let key_values = [] new_line = this.removeSpaces(new_line); for (let i = 0; i < new_line.length; i++) { if (new_line[i] === '"' || new_line[i] === "'") { inside_quote = !inside_quote; } if ((new_line[i] === "," || new_line[i] === ")") && inside_quote === false) { key_values.push(new_line.substring(last_index, i)); last_index = i + 1; } } return this.listToDict(key_values); } /** * Removes all whitespaces by also checking if it is inside quotes to not * disrupt passed Parameter string values * @param line String * @returns {string} */ removeSpaces(line) { let new_line = ""; let inside_quote = false; for (let i = 0; i < line.length; i++) { if (line[i] === '"' || line[i] === "'") { inside_quote = !inside_quote; } if (!(line[i] === " " && !inside_quote)) { new_line += line[i] } } return new_line; } /** * Transforms a list of arguments to a dict * @param list List of Strings * @returns {{}} */ listToDict(list) { const dict = {}; list.forEach(element => { let [key, value] = element.split('='); if (!isNaN(parseInt(value))) { dict[key] = parseInt(value); } else if (value){ dict[key] = value.replaceAll("'", ""); } }); return dict; } }