Advertisement
IzhanVarsky

Untitled

Apr 13th, 2019
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. "use strict";
  2.  
  3. let ind = 0;
  4. let expr = "";
  5.  
  6. function MyException(message) {
  7.     this.message = message
  8. }
  9.  
  10. function getFullByRegExp(reg) {
  11.     // /\d/ - digits
  12.     // /\s/ - blank space
  13.     // /\S/ - not blank space
  14.     // /[A-Za-z]/ - alphabetic
  15.     let res = "";
  16.     while (ind < expr.length && reg.test(expr[ind])) {
  17.         res += expr[ind];
  18.         ind++;
  19.     }
  20.     return res;
  21. }
  22.  
  23. function skipWhiteSpaces() {
  24.     while (ind < expr.length && /\s/.test(expr[ind])) {
  25.         ind++;
  26.     }
  27. }
  28.  
  29. function isNumber(s) {
  30.     if (s.length === 0) return false;
  31.     let pos = 0;
  32.     if (s[0] === '-' || s[0] === '+') {
  33.         if (s.length > 1) {
  34.             pos++;
  35.         } else {
  36.             return false;
  37.         }
  38.     }
  39.     while (pos < s.length) {
  40.         if (/\d/.test(s[pos])) {
  41.             pos++;
  42.         } else {
  43.             return false;
  44.         }
  45.     }
  46.     return true;
  47. }
  48.  
  49. function readBrackets() {
  50.     ind++; // вызывается всегда при '('
  51.     let operation = getNextToken();
  52.     if (!OPERATIONS.has(operation)) {
  53.         throw new MyException("Unknown operation: " + operation);
  54.     }
  55.     let op = getOperands();
  56.     if (OPERATIONS.get(operation)[1] !== 0 && OPERATIONS.get(operation)[1] !== op.length) {
  57.         throw new MyException("Operation: " + operation + ". Expected " +
  58.             OPERATIONS.get(operation)[1] + " arguments. Found: " + op);
  59.     }
  60.     return new (OPERATIONS.get(operation)[0])(...op);
  61. }
  62.  
  63. function getNextToken() {
  64.     skipWhiteSpaces();
  65.     return getFullByRegExp(/[^\s()]/);
  66. }
  67.  
  68. function getOperands() {
  69.     let curStack = []; // аргументы - тоже функции (инвариант)
  70.     while (true) {
  71.         skipWhiteSpaces();
  72.         let token = getNextToken();
  73.         if (isNumber(token)) {
  74.             curStack.push(new Const(parseInt(token, 10)));
  75.         } else if (token.length !== 0) {
  76.             if (!VARIABLES.has(token)) {
  77.                 throw new MyException("Unknown variable:" + token);
  78.             }
  79.             curStack.push(new Variable(token));
  80.         } else if (expr[ind] === '(') {
  81.             curStack.push(readBrackets());
  82.         } else if (expr[ind] === ')') {
  83.             ind++;
  84.             return curStack;
  85.         } else {
  86.             console.log("Never see it again: " + expr);
  87.             throw new MyException("Unexpected exception." + "Token: " + token + "Pos: " + ind + " Char: " + expr[ind]);
  88.         }
  89.     }
  90. }
  91.  
  92. function parsePrefix(str) {
  93.     expr = str;
  94.     ind = 0;
  95.     skipWhiteSpaces();
  96.     if (expr[ind] === '(') {
  97.         let res = readBrackets();
  98.         skipWhiteSpaces();
  99.         if (ind < expr.length) {
  100.             throw new MyException("Cannot parse next. Stopped on position: " + ind);
  101.         }
  102.         return res;
  103.     }
  104.     let token = getFullByRegExp(/\S/);
  105.     skipWhiteSpaces();
  106.     if (ind < expr.length) {
  107.         throw new MyException("Cannot parse next. Stopped on position: " + ind);
  108.     }
  109.     if (isNumber(token)) {
  110.         return new Const(parseInt(token, 10));
  111.     } else if (token.length !== 0) {
  112.         if (!VARIABLES.has(token)) {
  113.             throw new MyException("Unknown variable:" + token);
  114.         }
  115.         return new Variable(token);
  116.     }
  117.     console.log("Never see it again: " + expr);
  118.     throw new MyException("Cannot start parse. Stopped on position: " + ind);
  119. }
  120.  
  121. function newOperation(action, symbol) {
  122.     function Operation(...args) {
  123.         this.operands = args;
  124.     }
  125.  
  126.     Operation.prototype.toString = function () {
  127.         return this.operands.join(" ") + " " + symbol;
  128.     };
  129.     Operation.prototype.prefix = function () {
  130.         return "(" + symbol + " " + this.operands.map(value => value.prefix()).join(" ") + ")";
  131.     };
  132.     Operation.prototype.evaluate = function (...args) {
  133.         return action(...this.operands.map(operand => operand.evaluate(...args)));
  134.     };
  135.  
  136.     return Operation;
  137. }
  138.  
  139. function Const(x) {
  140.     this.value = x;
  141. }
  142.  
  143. Const.prototype.toString = function () {
  144.     return this.value.toString();
  145. };
  146. Const.prototype.evaluate = function () {
  147.     return this.value;
  148. };
  149. Const.prototype.prefix = Const.prototype.toString;
  150.  
  151. function Variable(s) {
  152.     this.name = s;
  153.     this.index = VARIABLES.get(s);
  154. }
  155.  
  156. Variable.prototype.toString = function () {
  157.     return this.name;
  158. };
  159. Variable.prototype.evaluate = function (...args) {
  160.     return args[this.index];
  161. };
  162. Variable.prototype.prefix = Variable.prototype.toString;
  163.  
  164. const Add = newOperation((a, b) => a + b, "+");
  165. const Subtract = newOperation((a, b) => a - b, "-");
  166. const Multiply = newOperation((a, b) => a * b, "*");
  167. const Divide = newOperation((a, b) => a / b, "/");
  168. const Negate = newOperation(a => -a, "negate");
  169. const Min3 = newOperation((a, b, c) => Math.min(a, b, c), "min3");
  170. const Max5 = newOperation((a, b, c, d, e) => Math.max(a, b, c, d, e), "max5");
  171. const Sum = newOperation((...args) => {
  172.     let sum = 0;
  173.     for (let k of args) {
  174.         sum += k;
  175.     }
  176.     return sum;
  177. }, "sum");
  178. const Avg = newOperation((...args) => {
  179.         let sum = 0;
  180.         for (let k of args) {
  181.             sum += k;
  182.         }
  183.         return sum / args.length; // Как поправить повтор?
  184.     }, "avg"
  185. );
  186.  
  187. const OPERATIONS = new Map([
  188.     ['+', [Add, 2]],
  189.     ['-', [Subtract, 2]],
  190.     ['*', [Multiply, 2]],
  191.     ['/', [Divide, 2]],
  192.     ['negate', [Negate, 1]],
  193.     ['min3', [Min3, 3]],
  194.     ['max5', [Max5, 5]],
  195.     ['sum', [Sum, 0]],
  196.     ['avg', [Avg, 0]],
  197.  
  198. ]);
  199.  
  200. const CONSTANTS = new Map([
  201.     ['one', 1],
  202.     ['two', 2],
  203.     ['pi', Math.PI],
  204.     ['e', Math.E]
  205. ]);
  206.  
  207. const VARIABLES = new Map([
  208.     ["x", 0],
  209.     ["y", 1],
  210.     ["z", 2]
  211. ]);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement