Skip to content

Commit

Permalink
Merge pull request #1 from javiercejudo/synonym-operators
Browse files Browse the repository at this point in the history
feat(op): handle synonyms for multiplication and division
  • Loading branch information
javiercejudo committed Jan 28, 2016
2 parents db63ca9 + 2515a07 commit a89ac06
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 19 deletions.
4 changes: 4 additions & 0 deletions package.json
Expand Up @@ -35,6 +35,10 @@
"dependencies": {
"arbitrary-precision": "^1.2.2",
"floating-adapter": "^1.3.0",
"lodash.assign": "^4.0.1",
"lodash.flow": "^3.2.1",
"lodash.isfunction": "^3.0.7",
"lodash.isundefined": "^3.0.1",
"ramda": "^0.19.1",
"remove-whitespace": "^1.1.0",
"to-decimal-arbitrary-precision": "^1.0.2"
Expand Down
25 changes: 24 additions & 1 deletion src/index.js
Expand Up @@ -3,16 +3,39 @@
'use strict';

var defaultTo = require('ramda/src/defaultTo');
var flow = require('lodash.flow');
var isFunction = require('lodash.isfunction');
var isUndefined = require('lodash.isundefined');
var assign = require('lodash.assign');
var decimalFactory = require('arbitrary-precision');
var floatingAdapter = require('floating-adapter');
var removeWhitespace = require('remove-whitespace');
var sy = require('../vendor/javascript-shunting-yard/shunt');
var operator = require('./operator');
var tokens = require('./tokens');

var defaultToFloating = defaultTo(decimalFactory(floatingAdapter));

sy.Context.prototype.def = function def(name, value) {
if (isUndefined(value) && isFunction(Math[name])) {
this.fnt[name] = Math[name];
} else if (isFunction(value)) {
this.fnt[name] = value;
} else {
this.cst[name] = value;
}

return this;
};

var opReplacer = function opReplacer(x) {
return x.replace(/×/g, '*').replace(/÷/g, '/');
};

var sanitise = flow(removeWhitespace, opReplacer);

var shuntingYard = function shuntingYard(xIn, specIn) {
var x = removeWhitespace(xIn);
var x = sanitise(xIn);
var spec = defaultTo({}, specIn);
var context = defaultTo(new sy.Context(), spec.context);
var Decimal = defaultToFloating(spec.Decimal);
Expand Down
26 changes: 8 additions & 18 deletions src/operator.js
Expand Up @@ -3,46 +3,36 @@
'use strict';

var toDecimalFactory = require('to-decimal-arbitrary-precision');

var T_PLUS = 65;
var T_MINUS = 66;
var T_TIMES = 67;
var T_DIV = 68;
var T_MOD = 69;
var T_POW = 70;
// var T_UNARY_PLUS = 71;
// var T_UNARY_MINUS = 72;
// var T_NOT = 73;
var T_SQRT = 74;
var tokens = require('./tokens');

module.exports = function op(origOp, Decimal) {
var toDecimal = toDecimalFactory(Decimal);

return function operator(type, lhs, rhs) {
if (lhs !== null) {
switch (type) {
case T_PLUS:
case tokens.T_PLUS:
return toDecimal(lhs.value).plus(toDecimal(rhs.value));

case T_MINUS:
case tokens.T_MINUS:
return toDecimal(lhs.value).minus(toDecimal(rhs.value));

case T_TIMES:
case tokens.T_TIMES:
return toDecimal(lhs.value).times(toDecimal(rhs.value));

case T_DIV:
case tokens.T_DIV:
return toDecimal(lhs.value).div(toDecimal(rhs.value));

case T_MOD:
case tokens.T_MOD:
return toDecimal(lhs.value).mod(toDecimal(rhs.value));

case T_POW:
case tokens.T_POW:
return toDecimal(lhs.value).pow(toDecimal(rhs.value));
}
}

switch (type) {
case T_SQRT:
case tokens.T_SQRT:
return toDecimal(rhs.value).sqrt();
}

Expand Down
42 changes: 42 additions & 0 deletions src/tokens.js
@@ -0,0 +1,42 @@
/*jshint node:true */

'use strict';

// tokens
var T_NUMBER = 1, // number
T_IDENT = 2, // ident (constant)
T_FUNCTION = 4, // function
T_POPEN = 8, // (
T_PCLOSE = 16, // )
T_COMMA = 32, // ,
T_OPERATOR = 64, // operator
T_PLUS = 65, // +
T_MINUS = 66, // -
T_TIMES = 67, // *
T_DIV = 68, // /
T_MOD = 69, // %
T_POW = 70, // ^
T_UNARY_PLUS = 71, // unary +
T_UNARY_MINUS = 72, // unary -
T_NOT = 73, // unary ! (convert (n > 0 || n < 0) to 0 and 0 to 1)
T_SQRT = 74; // unary √

module.exports = {
T_NUMBER: T_NUMBER,
T_IDENT: T_IDENT,
T_FUNCTION: T_FUNCTION,
T_POPEN: T_POPEN,
T_PCLOSE: T_PCLOSE,
T_COMMA: T_COMMA,
T_OPERATOR: T_OPERATOR,
T_PLUS: T_PLUS,
T_MINUS: T_MINUS,
T_TIMES: T_TIMES,
T_DIV: T_DIV,
T_MOD: T_MOD,
T_POW: T_POW,
T_UNARY_PLUS: T_UNARY_PLUS,
T_UNARY_MINUS: T_UNARY_MINUS,
T_NOT: T_NOT,
T_SQRT: T_SQRT
};
3 changes: 3 additions & 0 deletions test/spec.js
Expand Up @@ -26,6 +26,9 @@ describe('shunt', function() {
shunt('9^.5').equals(toFloating(3)).should.be.exactly(true);
shunt('11%3').equals(toFloating(2)).should.be.exactly(true);
shunt('√1024').equals(toFloating(32)).should.be.exactly(true);

shunt('3×2').equals(toFloating(6)).should.be.exactly(true);
shunt('10÷5').equals(toFloating(2)).should.be.exactly(true);
});

it('supports arbitrary precision', function() {
Expand Down

0 comments on commit a89ac06

Please sign in to comment.