UNPKG

@masala/parser

Version:
180 lines (129 loc) 5.76 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); var _genlex = require('../../lib/genlex/genlex'); var _index = require('../../lib/parsec/index'); var _index2 = require('../../lib/stream/index'); var _index3 = _interopRequireDefault(_index2); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /* Implementing general solution : E -> T E' E' -> + TE' | eps T -> F T' T' -> * FT' | eps F -> NUMBER | ( E ) (https://en.wikipedia.org/wiki/Operator-precedence_parser) * Expr -> SubExpr then OptYieldExpr * OptYieldExpr -> YieldExpr.opt() * YieldExpr -> + then SubExpr then YieldExpr * PriorExpr -> Terminal then OptPriorExpr * OptPriorExpr -> PriorExpr.opt() * PriorExpr -> * then Terminal then OptPriorExpr * Terminal -> (Expr)| Number | -Terminal | Expr // care of priority ! */ // tokens var genlex = (0, _genlex.getMathGenLex)(); var _genlex$tokens = genlex.tokens(), number = _genlex$tokens.number, plus = _genlex$tokens.plus, minus = _genlex$tokens.minus, mult = _genlex$tokens.mult, div = _genlex$tokens.div, open = _genlex$tokens.open, close = _genlex$tokens.close; var priorToken = function priorToken() { return mult.or(div); }; var yieldToken = function yieldToken() { return plus.or(minus); }; function terminal() { return parenthesis().or(number).or(negative()).or(_index.F.lazy(expression)); } function negative() { return minus.drop().then(_index.F.lazy(terminal)).single().map(function (x) { return -x; }); } function parenthesis() { return open.drop().then(_index.F.lazy(expression)).then(close.drop()).single(); } function expression() { return priorExpr().flatMap(optYieldExpr); } function optYieldExpr(left) { return yieldExpr(left).opt().map(function (opt) { return opt.isPresent() ? opt.get() : left; }); } function yieldExpr(left) { return yieldToken().then(priorExpr()).array().map(function (_ref) { var _ref2 = _slicedToArray(_ref, 2), token = _ref2[0], right = _ref2[1]; return token === '+' ? left + right : left - right; }).flatMap(optYieldExpr); } function priorExpr() { return terminal().flatMap(optSubPriorExp); } function optSubPriorExp(priorValue) { return subPriorExpr(priorValue).opt().map(function (opt) { return opt.isPresent() ? opt.get() : priorValue; }); } function subPriorExpr(priorValue) { return priorToken().then(terminal()).array().map(function (_ref3) { var _ref4 = _slicedToArray(_ref3, 2), token = _ref4[0], left = _ref4[1]; return token === '*' ? priorValue * left : priorValue / left; }).flatMap(optSubPriorExp); } function multParser() { var parser = expression(); return genlex.use(parser.then(_index.F.eos().drop()).single()); } exports.default = { setUp: function setUp(done) { done(); }, 'expect multExpr to make mults': function expectMultExprToMakeMults(test) { var parsing = multParser().parse(_index3.default.ofString('3 * 4')); test.equal(parsing.value, 12, 'simple multiplication'); parsing = multParser().parse(_index3.default.ofString('14 / 4')); test.equal(parsing.value, 3.5, 'simple division'); parsing = multParser().parse(_index3.default.ofString('14 / 4*3 ')); test.equal(parsing.value, 10.5, 'combine mult and div'); parsing = multParser().parse(_index3.default.ofString('14 / 4*3 /2* 2 ')); test.equal(parsing.value, 10.5, 'combine more mult and div'); test.done(); }, 'expect multExpr to make negative priorities': function expectMultExprToMakeNegativePriorities(test) { var parsing = multParser().parse(_index3.default.ofString('3 * -4')); test.equal(parsing.value, -12, 'negative multiplication'); test.done(); }, 'expect Expr to be inside parenthesis': function expectExprToBeInsideParenthesis(test) { var parsing = multParser().parse(_index3.default.ofString('3 * (4)')); test.equal(parsing.value, 12, 'simple parenthesis expr'); parsing = multParser().parse(_index3.default.ofString('3 * (2*4)')); test.equal(parsing.value, 24, 'more complexe parenthesis expr'); parsing = multParser().parse(_index3.default.ofString('3 * (2*(4))')); test.equal(parsing.value, 24, 'deep parenthesis expr'); test.done(); }, 'expect + and * to respect priorities': function expectAndToRespectPriorities(test) { var parsing = multParser().parse(_index3.default.ofString('3 +2*4 ')); test.equal(parsing.value, 11, 'simple multiplication'); test.done(); }, 'expect - and / to respect priorities': function expectAndToRespectPriorities(test) { var parsing = multParser().parse(_index3.default.ofString('3 + -4/2*5 ')); test.equal(parsing.value, -7, 'bad priorities'); test.done(); } }; //# sourceMappingURL=genlex-operation.js.map