Advertisement
Guest User

Untitled

a guest
May 25th, 2018
170
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. function importPackage(pack) {
  2.     for (var x in pack) {
  3.         global[x] = pack[x];
  4.     }
  5. }
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13. var exceptions = (function () {
  14.     function MyException(message) { this.message = message }
  15.     MyException.prototype = Error.prototype;
  16.     MyException.prototype.name = "MyException";
  17.  
  18.     function MakeException(name) { this.name = name }
  19.     MakeException.prototype = MyException.prototype;
  20.  
  21.     function exceptionFactory(name, newMess) {
  22.         var result = function () {
  23.             MyException.call(this, newMess.apply(null, arguments));
  24.         }
  25.         result.prototype = new MakeException(name);
  26.         return result;
  27.     }
  28.  
  29.     var OddClosingParenthesisException = exceptionFactory(
  30.         "OddClosingParenthesisException",
  31.         function (expr, ind) {
  32.             return ("Odd closing bracket at position: " + ind + "\n" + expr);
  33.         }
  34.     );
  35.  
  36.     var MissingClosingParenthesisException = exceptionFactory(
  37.         "MissingClosingParenthesisException",
  38.         function (expr, ind) {
  39.             return ("Expected closing bracket before position: " + ind + "\n" + expr);
  40.         }
  41.     );
  42.  
  43.     var MissingOpeationParenthesisException = exceptionFactory(
  44.         "MissingOpeationParenthesisException",
  45.         function (expr, op, ind, mode) {
  46.             var ending = op + "' at position: " + ind + "\n" + expr;
  47.             if (!mode) {
  48.                 return ("Opening bracket expected before operation '" + ending);
  49.             } else {
  50.                 return ("Closing bracket expected after operation '" + ending);
  51.             }
  52.         }
  53.     );
  54.  
  55.     var MissingOperandException = exceptionFactory(
  56.         "MissingOperandException",
  57.         function (expr, op, ind) {
  58.             return ("Overflow operands for operation '" + op + "' at position: " + ind + "\n" + expr );
  59.         }
  60.     );
  61.  
  62.     var OddOperandException = exceptionFactory(
  63.         "OddOperandException",
  64.         function (expr, op, ind) {
  65.             return ("Too many operands for operation '" + op + "' at position: " + ind + "\n" + expr);
  66.         }
  67.     );
  68.  
  69.     var UnknownIdentifierException = exceptionFactory(
  70.         "UnknownIdentifierException",
  71.         function (expr, id, ind) {
  72.             return ("Unknown identifier '" + id + "' at position: " + ind + "\n" + expr);
  73.         }
  74.     );
  75.  
  76.     var UnknownSymbolException = exceptionFactory(
  77.         "UnknownSymbolException",
  78.         function (expr, ind) {
  79.             return ("Unknown symbol '" + expr.charAt(ind) + "' at position: " + ind + "\n" + expr);
  80.         }
  81.     );
  82.  
  83.     var MissingOperationException = exceptionFactory(
  84.         "MissingOperationException",
  85.         function (expr, ind, where) {
  86.             var reason = "";
  87.             if (!where) {
  88.                 reason = "Expected operation after opening bracket at position ";
  89.             } else {
  90.                 reason = "Expected operation before closing bracket at position ";
  91.             }
  92.             return (reason + ind + "\n" + expr);
  93.         }
  94.     );
  95.  
  96.     var OddSuffixException = exceptionFactory(
  97.         "OddSuffixException",
  98.         function (expr, ind) {
  99.             return ("Unexpected suffix after correct expression at position: " + ind  + "\n" + expr);
  100.         }
  101.     );
  102.  
  103.     return {
  104.         "MyException": MyException,
  105.         "OddClosingParenthesisException": OddClosingParenthesisException,
  106.         "MissingClosingParenthesisException": MissingClosingParenthesisException,
  107.         "MissingOperandException": MissingOperandException,
  108.         "UnknownIdentifierException": UnknownIdentifierException,
  109.         "UnknownSymbolException": UnknownSymbolException,
  110.         "MissingOperationException": MissingOperationException,
  111.         "OddSuffixException": OddSuffixException,
  112.         "OddOperandException": OddOperandException,
  113.         "MissingOpeationParenthesisException": MissingOpeationParenthesisException
  114.     }
  115. })();
  116.  
  117.  
  118.  
  119.  
  120.  
  121.  
  122. var expression = (function () {
  123.     importPackage(exceptions);
  124.  
  125.     function myNew(constructor, args) {
  126.         var tmp = Object.create(constructor.prototype);
  127.         constructor.apply(tmp, args);
  128.         return tmp;
  129.     }
  130.  
  131.     var VARIABLES = {"x": 0, "y": 1, "z": 2};
  132.     function Const(x) {
  133.         this.getValue = function () { return x }
  134.     }
  135.     Const.prototype.toString = function () { return this.getValue().toString() }
  136.     Const.prototype.prefix = Const.prototype.toString;
  137.     Const.prototype.evaluate = function () { return this.getValue() }
  138.  
  139.     function Variable(s) {
  140.         var ind = VARIABLES[s];
  141.         this.getName = function () { return s }
  142.         this.getInd = function () { return ind }
  143.     }
  144.  
  145.     Variable.prototype.toString = function () { return this.getName() }
  146.     Variable.prototype.prefix = Variable.prototype.toString;
  147.     Variable.prototype.evaluate = function () { return arguments[this.getInd()] }
  148.  
  149.     function Operation() {
  150.         var operands = [].slice.call(arguments);
  151.         this.getOperands = function () { return operands }
  152.     }
  153.     Operation.prototype.toString = function () {
  154.         return this.getOperands().join(" ") + " " + this.getSymbol();
  155.     }
  156.     Operation.prototype.prefix = function () {
  157.         return "(" +  this.getSymbol() + " " + this.getOperands().map(function (value) { return value.prefix() }).join(" ") + ")";
  158.     }
  159.     Operation.prototype.evaluate = function () {
  160.         var args = arguments;
  161.         var res = this.getOperands().map(function(value) { return value.evaluate.apply(value, args) });
  162.         return this._action.apply(null, res);
  163.     }
  164.  
  165.     function flag(a) {
  166.         return (a instanceof Const || a instanceof Variable || a instanceof Operation);
  167.     }
  168.  
  169.     function DefineOperation(action, symbol) {
  170.         this._action = action;
  171.         this.getSymbol = function () {
  172.             return symbol;
  173.         }
  174.     }
  175.     DefineOperation.prototype = Operation.prototype;
  176.  
  177.     function operationFactory(action, symbol) {
  178.         var result = function () {
  179.             var args = arguments;
  180.             Operation.apply(this, args);
  181.         }
  182.         result.prototype = new DefineOperation(action, symbol);
  183.         return result;
  184.     }
  185.  
  186.     var Add = operationFactory(
  187.         function (a, b) { return a + b },
  188.         "+"
  189.     );
  190.  
  191.     var Subtract = operationFactory(
  192.         function (a, b) { return a - b },
  193.         "-"
  194.     );
  195.  
  196.     var Multiply = operationFactory(
  197.         function (a, b) { return a * b },
  198.         "*"
  199.     );
  200.  
  201.     var Divide = operationFactory(
  202.         function (a, b) { return a / b },
  203.         "/"
  204.     );
  205.  
  206.     var Negate = operationFactory(
  207.         function (a) { return -a },
  208.         "negate"
  209.     );
  210.  
  211.     var ArcTan = operationFactory(
  212.         function (a) { return Math.atan(a) },
  213.         "atan"
  214.     );
  215.  
  216.     var Exp = operationFactory(
  217.         function (a) {return Math.exp(a) },
  218.         "exp"
  219.     );
  220.  
  221.     var OP = {
  222.         "+": Add,
  223.         "-": Subtract,
  224.         "*": Multiply,
  225.         "/": Divide,
  226.         "negate": Negate,
  227.         "atan": ArcTan,
  228.         "exp": Exp
  229.     };
  230.     var ARGS_COUNT = {
  231.         "+": 2,
  232.         "-": 2,
  233.         "*": 2,
  234.         "/": 2,
  235.         "negate": 1,
  236.         "atan": 1,
  237.         "exp": 1
  238.     };
  239.  
  240.     var expr = "";
  241.     var ind = 0;
  242.     var stack = [];
  243.     var index = [];
  244.  
  245.     function skipWhiteSpace() {
  246.         while (ind < expr.length && /\s/.test(expr.charAt(ind))) {
  247.             ind++;
  248.         }
  249.     }
  250.  
  251.  
  252.     function parsePrefix(s) {
  253.         var balance = 0;
  254.         ind = 0;
  255.         expr = s;
  256.         stack = [];
  257.         skipWhiteSpace();
  258.         if (ind === expr.length) {
  259.             throw new MyException("Empty input");
  260.         }
  261.         var mode = 0;
  262.         while (true) {
  263.             skipWhiteSpace();
  264.             if (ind >= expr.length) {
  265.                 break;
  266.             }
  267.             if (expr.charAt(ind) === ")") {
  268.                 balance--;
  269.                 if (balance < 0) {
  270.                     throw new OddClosingParenthesisException(expr, ind);
  271.                 }
  272.  
  273.                 var tempInd = undefined;
  274.                 var curOperation = undefined;
  275.                 var operands = [];
  276.                 while ((stack[stack.length - 1] !== "(") && !(stack[stack.length - 1] in OP)) {
  277.                     operands.push(stack.pop());
  278.                     index.pop();
  279.                 }
  280.                 if (stack[stack.length - 1] === "(") {
  281.                     throw new MissingOperationException(expr, index.pop(), mode);
  282.                 }
  283.                 curOperation = stack.pop();
  284.                 tempInd = index.pop();
  285.                 if (stack.pop() !== "(") {
  286.                     throw new MissingOpeationParenthesisException(expr, curOperation, index.pop(), mode);
  287.                 }
  288.                 index.pop()
  289.                 if (operands.length > ARGS_COUNT[curOperation]) {
  290.                     throw new OddOperandException(expr, curOperation, tempInd);
  291.                 } else if (operands.length < ARGS_COUNT[curOperation]) {
  292.                     throw new MissingOperandException(expr, curOperation, tempInd);
  293.                 } else {
  294.                     stack.push(myNew(OP[curOperation], operands.reverse()));
  295.                 }
  296.  
  297.                 ind++;
  298.                 if (balance === 0) {
  299.                     break;
  300.                 }
  301.                 continue;
  302.             }
  303.             index.push(ind);
  304.             if (expr.charAt(ind) === "(") {
  305.                 stack.push("(");
  306.                 ind++;
  307.                 balance++;
  308.                 continue;
  309.             }
  310.  
  311.             var curNumber = "";
  312.  
  313.             if (expr.charAt(ind) === "-") {
  314.                 curNumber += "-";
  315.                 ind++;
  316.             }
  317.             while (ind < expr.length && /\d/.test(expr.charAt(ind))) {
  318.                 curNumber += expr.charAt(ind++);
  319.             }
  320.  
  321.             if (curNumber !== "" && curNumber !== "-") {
  322.                 stack.push(new Const(parseInt(curNumber)));
  323.                 continue;
  324.             } else {
  325.                 if (curNumber === "-") {
  326.                     ind--;
  327.                 }
  328.             }
  329.             var curOp = undefined;
  330.             var curId;
  331.             if (expr.charAt(ind) in OP) {
  332.                 curOp = expr.charAt(ind);
  333.                 ind++;
  334.             } else {
  335.                 curId = "";
  336.  
  337.                 if (!(/[A-Za-z]/.test(expr.charAt(ind)))) {
  338.                     throw new UnknownSymbolException(expr, ind);
  339.                 }
  340.                 while (ind < expr.length && /\w/.test(expr.charAt(ind))) {
  341.                     curId += expr.charAt(ind++);
  342.                 }
  343.  
  344.                 if (curId in OP) {
  345.                     curOp = curId;
  346.                 }
  347.             }
  348.             if (curOp !== undefined) {
  349.                 stack.push(curOp);
  350.             } else if (curId in VARIABLES) {
  351.                 stack.push(new Variable(curId));
  352.                 if (balance === 0) {
  353.                     break;
  354.                 }
  355.             } else {
  356.                 throw new UnknownIdentifierException(expr, curId, index.pop());
  357.             }
  358.         }
  359.         skipWhiteSpace();
  360.         if (ind !== expr.length) {
  361.             throw new OddSuffixException(expr, ind);
  362.         } else if (balance > 0) {
  363.             throw new MissingClosingParenthesisException(expr, ind);
  364.         } else if (stack.length > 1) {
  365.             throw new MissingOpeationParenthesisException(expr, stack[0], index[0], mode);
  366.         }
  367.         var res = stack.pop();
  368.         if (!flag(res)) {
  369.             throw new MissingOpeationParenthesisException(expr, res, index.pop(), mode);
  370.         }
  371.         return res;
  372.     }
  373.  
  374.     return {
  375.         "Const": Const,
  376.         "Variable": Variable,
  377.         "Add": Add,
  378.         "Subtract": Subtract,
  379.         "Multiply": Multiply,
  380.         "Divide": Divide,
  381.         "Negate": Negate,
  382.         "parsePrefix": parsePrefix,
  383.         "ArcTan": ArcTan,
  384.         "Exp": Exp
  385.     }
  386.  
  387. })();
  388.  
  389.  
  390.  
  391.  
  392.  
  393.  
  394.  
  395.  
  396.  
  397.  
  398. importPackage(expression);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement