Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const indexes = new Map();
- indexes.set("x", 0);
- indexes.set("y", 1);
- indexes.set("z", 2);
- function createBy(constructor, args) {
- let instance = Object.create(constructor.prototype);
- constructor.apply(instance, args);
- return instance;
- }
- function constructOperation(basicOperation, operationIdentifier) {
- function Operation(...args) {
- this.operands = args;
- }
- Operation.prototype.toString = function () {
- return this.operands.join(" ") + " " + operationIdentifier;
- };
- Operation.prototype.evaluate = function (...args) {
- return basicOperation(...this.operands.map(operand => operand.evaluate(...args)));
- };
- Operation.prototype.prefix = function () {
- return "(" + operationIdentifier + " " + this.operands.map(operand => operand.prefix()).join(" ") + ")";
- };
- return Operation;
- }
- function Const(value) {
- this.constValue = value;
- }
- Const.prototype.toString = function () {
- return this.constValue.toString();
- };
- Const.prototype.evaluate = function () {
- return this.constValue;
- };
- Const.prototype.prefix = function () {
- return this.constValue.toString();
- };
- function Variable(name) {
- this.variableName = name;
- this.index = indexes.get(name);
- }
- Variable.prototype.toString = function () {
- return this.variableName;
- };
- Variable.prototype.evaluate = function () {
- return arguments[this.index];
- };
- Variable.prototype.prefix = function () {
- return this.variableName;
- };
- let Add = constructOperation((x, y) => (x + y), "+");
- let Subtract = constructOperation((x, y) => (x - y), "-");
- let Multiply = constructOperation((x, y) => (x * y), "*");
- let Divide = constructOperation((x, y) => (x / y), "/");
- let Negate = constructOperation((x) => (-x), "negate");
- let Min3 = constructOperation((...args) => Math.min(...args), "min3");
- let Max5 = constructOperation((...args) => (Math.max(...args)), "max5");
- let operations = {};
- operations['+'] = {Op: Add, argsCount: 2};
- operations['-'] = {Op: Subtract, argsCount: 2};
- operations['*'] = {Op: Multiply, argsCount: 2};
- operations['/'] = {Op: Divide, argsCount: 2};
- operations['negate'] = {Op: Negate, argsCount: 1};
- let exceptions = function () {
- let exceptionFactory = function (message) {
- let Exception = function (index, token) {
- this.name = message + " on position " + index + ", where '" + token + "' is";
- };
- Exception.prototype = Error.prototype;
- return Exception;
- };
- let ClosingParenthesisMissingException = exceptionFactory(
- 'Closing parenthesis expected'
- );
- let ExpressionEndExpectedException = exceptionFactory(
- 'End of expression expected'
- );
- let OperationExpectedException = exceptionFactory(
- 'Operation symbol expected'
- );
- let OperandExpectedException = exceptionFactory(
- 'Operand expected'
- );
- let EndOfConstantExpectedException = exceptionFactory(
- 'End of constant expected'
- );
- let InvalidOperandsAmountException = exceptionFactory(
- 'Invalid operands amount found'
- );
- return {
- ClosingParenthesisMissingException: ClosingParenthesisMissingException,
- ExpressionEndExpectedException: ExpressionEndExpectedException,
- OperationExpectedException: OperationExpectedException,
- OperandExpectedException: OperandExpectedException,
- EndOfConstantExpectedException: EndOfConstantExpectedException,
- InvalidOperandsAmountException: InvalidOperandsAmountException,
- }
- }();
- let Tokenizer = function (string) {
- this.index = 0;
- this.prevToken = '';
- this.curToken = '';
- let isWhitespace = function (c) {
- return /[\s]/.test("" + c);
- };
- this.nextToken = function () {
- this.prevToken = this.curToken;
- while (this.index < string.length && isWhitespace(string[this.index])) {
- this.index++;
- }
- this.curToken = '';
- if (string[this.index] === '(' || string[this.index] === ')') {
- this.curToken = string[this.index++];
- } else {
- while (this.index < string.length &&
- !isWhitespace(string[this.index]) && string[this.index] !== '(' && string[this.index] !== ')') {
- this.curToken += string[this.index++];
- }
- }
- };
- };
- let parseOperand = function (tokenizer, parseExpression) {
- if (tokenizer.curToken === '(') {
- return parseExpression();
- } else if (indexes.has(tokenizer.curToken)) {
- tokenizer.nextToken();
- return new Variable(tokenizer.prevToken)
- } else if (tokenizer.curToken !== '' && !isNaN(tokenizer.curToken)) {
- tokenizer.nextToken();
- return new Const(parseInt(tokenizer.prevToken));
- } else {
- throw new exceptions.OperandExpectedException(tokenizer.index, tokenizer.curToken);
- }
- };
- let parsePrefix = function (str) {
- let tokenizer = new Tokenizer(str);
- let parseExpression = function () {
- if (tokenizer.curToken === '(') {
- tokenizer.nextToken();
- if (!(tokenizer.curToken in operations)) {
- throw new exceptions.OperationExpectedException(tokenizer.index, tokenizer.curToken);
- }
- let operation = operations[tokenizer.curToken];
- tokenizer.nextToken();
- let args = [];
- for (let i = 0; i < operation.argsCount; i++) {
- args.push(parseOperand(tokenizer, parseExpression));
- }
- if (tokenizer.curToken !== ')') {
- throw new exceptions.ClosingParenthesisMissingException(tokenizer.index, tokenizer.curToken);
- }
- tokenizer.nextToken();
- //return operation.Op(args);
- //return createBy(operation.Op, args);
- return new operation.Op.apply(args);
- } else {
- return parseOperand(tokenizer, parseExpression);
- }
- };
- tokenizer.nextToken();
- let res = parseExpression();
- if (tokenizer.curToken !== '') {
- throw new exceptions.ExpressionEndExpectedException(tokenizer.index, tokenizer.curToken);
- }
- return res;
- };
- /*
- let expr = new Subtract(
- new Multiply(
- new Const(2),
- new Variable("x")
- ),
- new Const(3)
- );
- console.log(expr.toString());*/
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement