Created
September 26, 2015 14:10
-
-
Save mjnaderi/3bb3be3d244495d7e559 to your computer and use it in GitHub Desktop.
Simple math expression evaluator based on jsep
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var jsep = require('jsep'); | |
(function (root) { | |
var COMPOUND = 'Compound', | |
IDENTIFIER = 'Identifier', | |
MEMBER_EXP = 'MemberExpression', | |
LITERAL = 'Literal', | |
THIS_EXP = 'ThisExpression', | |
CALL_EXP = 'CallExpression', | |
UNARY_EXP = 'UnaryExpression', | |
BINARY_EXP = 'BinaryExpression', | |
LOGICAL_EXP = 'LogicalExpression', | |
CONDITIONAL_EXP = 'ConditionalExpression', | |
ARRAY_EXP = 'ArrayExpression'; | |
var functions = { | |
'abs': Math.abs, | |
'floor': Math.floor, | |
'ceil': Math.ceil, | |
'exp': Math.exp, | |
'sqrt': Math.sqrt, | |
'log': Math.log, | |
'log10': Math.log10 | |
}; | |
function isNumeric(n) { | |
return !isNaN(parseFloat(n)) && isFinite(n); | |
} | |
var evalTree = function (tree, context) { | |
if (tree === false || typeof tree === 'undefined') | |
throw 'خطایی در عبارت ریاضی داده شده وجود دارد.'; | |
if (tree.type === LITERAL) { | |
if (!(isNumeric(tree.value))) | |
throw 'تنها مقادیر عددی قابل قبول هستند.'; | |
return tree.value; | |
} | |
if (tree.type == IDENTIFIER) { | |
if (typeof context === 'undefined') | |
throw 'ورودی context داده نشده است'; | |
if (tree.name in context) | |
return context[tree.name]; | |
throw 'مقدار ' + tree.name + ' تعریف نشده است.'; | |
} | |
if (tree.type === UNARY_EXP) { | |
if (tree.operator === '+') | |
return evalTree(tree.argument, context); | |
if (tree.operator === '-') | |
return -evalTree(tree.argument, context); | |
throw 'عملگر یگانی ' + tree.operator + ' پشتیبانی نمیشود.'; | |
} | |
if (tree.type === BINARY_EXP) { | |
if (tree.operator === '+') | |
return evalTree(tree.left, context) + evalTree(tree.right, context); | |
if (tree.operator === '-') | |
return evalTree(tree.left, context) - evalTree(tree.right, context); | |
if (tree.operator === '*') | |
return evalTree(tree.left, context) * evalTree(tree.right, context); | |
if (tree.operator === '/') | |
return evalTree(tree.left, context) / evalTree(tree.right, context); | |
if (tree.operator === '%') | |
return evalTree(tree.left, context) % evalTree(tree.right, context); | |
if (tree.operator === '^') | |
return Math.pow(evalTree(tree.left, context), evalTree(tree.right, context)); | |
throw 'عملگر دوگانی ' + tree.operator + ' پشتیبانی نمیشود.'; | |
} | |
if (tree.type === CALL_EXP) { | |
if (tree.callee.type !== IDENTIFIER) | |
throw 'عمل ریاضی وارد شده پشتیبانی نمیشود.'; | |
if (tree.arguments.length > 1) | |
throw 'امکان استفاده از توابع با بیش از یک ورودی وجود ندارد.'; | |
if (!(tree.callee.name in functions)) | |
throw 'تابع ' + tree.callee.name + ' پشتیبانی نمیشود.'; | |
return functions[tree.callee.name](evalTree(tree.arguments[0], context)); | |
} | |
throw 'عبارت ریاضی دادهشده پشتیبانی نمیشود و یا عبارت دادهشده خطا دارد.'; | |
}; | |
queval = function (expression, context) { | |
var tree = jsep(expression); | |
return evalTree(tree, context); | |
}; | |
// In desktop environments, have a way to restore the old value for `queval` | |
if (typeof exports === 'undefined') { | |
var old_queval = root.queval; | |
// The star of the show! It's a function! | |
root.queval = queval; | |
// And a courteous function willing to move out of the way for other similarly-named objects! | |
queval.noConflict = function () { | |
if (root.queval === queval) { | |
root.queval = old_queval; | |
} | |
return queval; | |
}; | |
} else { | |
// In Node.JS environments | |
if (typeof module !== 'undefined' && module.exports) { | |
exports = module.exports = queval; | |
} else { | |
exports.parse = queval; | |
} | |
} | |
}(this)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment