Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- "use strict";
- let ind = 0;
- let expr = "";
- function MyException(message) {
- this.message = message
- }
- function getFullByRegExp(reg) {
- // /\d/ - digits
- // /[A-Za-z]/ - alphabetic
- let res = "";
- while (ind < expr.length && reg.test(expr[ind])) {
- res += expr[ind];
- ind++;
- }
- return res;
- }
- function skipWhiteSpaces() {
- while (ind < expr.length && /\s/.test(expr[ind])) {
- ind++;
- }
- }
- function checkDigits(s) {
- if (s.length === 0) return false;
- let pos = 0;
- if (s[0] === '-' || s[0] === '+') {
- if (s.length > 1) {
- pos++;
- } else {
- return false;
- }
- }
- while (pos < s.length) {
- if (/\d/.test(s[pos])) {
- pos++;
- } else {
- return false;
- }
- }
- return true;
- }
- function readBrackets() {
- ind++;
- let operation = getOperation();
- if (!OPERATIONS.has(operation)) {
- throw new MyException("Unknown operation: " + operation);
- }
- let op = getOperands();
- if (OPERATIONS.get(operation)[1] !== op.length) {
- throw new MyException("Operation: " + operation + ". Expected " +
- OPERATIONS.get(operation)[1] + "arguments. Found: " + op);
- }
- switch (operation) {
- case "+": {
- return new Add(op[0], op[1]);
- }
- case "-": {
- return new Subtract(op[0], op[1]);
- }
- case "*": {
- return new Multiply(op[0], op[1]);
- }
- case "/": {
- return new Divide(op[0], op[1]);
- }
- case "negate": {
- return new Negate(op[0]);
- }
- }
- // return (OPERATIONS.get(operation)[0]).apply(op); ????
- }
- function getOperation() {
- skipWhiteSpaces();
- let token = "";
- while (ind < expr.length && /\S/.test(expr[ind]) && !/[()]/.test(expr[ind])) {
- token += expr[ind];
- ind++;
- }
- return token;
- }
- function getOperands() {
- let curStack = []; // аргументы - тоже функции (инвариант)
- while (true) {
- skipWhiteSpaces();
- let token = "";
- while (ind < expr.length && /\S/.test(expr[ind]) && !/[()]/.test(expr[ind])) {
- token += expr[ind];
- ind++;
- }
- skipWhiteSpaces();
- // let token = getFullByRegExp(/\S[^()]/); ????
- if (checkDigits(token)) {
- curStack.push(new Const(parseInt(token, 10)));
- continue;
- } else if (token.length !== 0) {
- if (!VARIABLES.has(token)) {
- throw new MyException("Unknown variable:" + token);
- }
- curStack.push(new Variable(token));
- continue;
- }
- skipWhiteSpaces();
- if (expr[ind] === '(') {
- curStack.push(readBrackets());
- } else if (expr[ind] === ')') {
- ind++;
- return curStack;
- } else {
- throw new MyException("Unexpected exception." + "Token: " + token + "Pos: " + ind + " Char: " + expr[ind]);
- }
- }
- }
- function parsePrefix(str) {
- expr = str;
- ind = 0;
- skipWhiteSpaces();
- if (expr[ind] === '(') {
- let res = readBrackets();
- skipWhiteSpaces();
- if (ind < expr.length) {
- throw new MyException("Cannot parse next. Stopped on position: " + ind);
- }
- return res;
- }
- let token = getFullByRegExp(/\S/);
- skipWhiteSpaces();
- if (ind < expr.length) {
- throw new MyException("Cannot parse next. Stopped on position: " + ind);
- }
- if (checkDigits(token)) {
- return new Const(parseInt(token, 10));
- } else if (token.length !== 0) {
- if (!VARIABLES.has(token)) {
- throw new MyException("Unknown variable:" + token);
- }
- return new Variable(token);
- }
- throw new MyException("Cannot start parse. Stopped on position: " + ind);
- }
- function newOperation(action, symbol) {
- function Operation(...args) {
- this.operands = args;
- }
- Operation.prototype.toString = function () {
- return this.operands.join(" ") + " " + symbol;
- };
- Operation.prototype.prefix = function () {
- return "(" + symbol + " " + this.operands.map(value => value.prefix()).join(" ") + ")";
- };
- Operation.prototype.evaluate = function (...args) {
- return action(...this.operands.map(operand => operand.evaluate(...args)));
- };
- return Operation;
- }
- function Const(x) {
- this.value = x;
- }
- Const.prototype.toString = function () {
- return this.value.toString();
- };
- Const.prototype.evaluate = function () {
- return this.value;
- };
- Const.prototype.prefix = Const.prototype.toString;
- function Variable(s) {
- this.name = s;
- this.index = VARIABLES.get(s);
- }
- Variable.prototype.toString = function () {
- return this.name;
- };
- Variable.prototype.evaluate = function (...args) {
- return args[this.index];
- };
- Variable.prototype.prefix = Variable.prototype.toString;
- const Add = newOperation((a, b) => a + b, "+");
- const Subtract = newOperation((a, b) => a - b, "-");
- const Multiply = newOperation((a, b) => a * b, "*");
- const Divide = newOperation((a, b) => a / b, "/");
- const Negate = newOperation(a => -a, "negate");
- const Min3 = newOperation((a, b, c) => Math.min(a, b, c), "min3");
- const Max5 = newOperation((a, b, c, d, e) => Math.max(a, b, c, d, e), "max5");
- const OPERATIONS = new Map([
- ['+', [Add, 2]],
- ['-', [Subtract, 2]],
- ['*', [Multiply, 2]],
- ['/', [Divide, 2]],
- ['negate', [Negate, 1]],
- ['min3', [Min3, 3]],
- ['max5', [Max5, 5]]
- ]);
- const CONSTANTS = new Map([
- ['one', 1],
- ['two', 2],
- ['pi', Math.PI],
- ['e', Math.E]
- ]);
- const VARIABLES = new Map([
- ["x", 0],
- ["y", 1],
- ["z", 2]
- ]);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement