Skip to content

Instantly share code, notes, and snippets.

@alanrsoares
Last active August 29, 2015 14:00
Show Gist options
  • Save alanrsoares/11126970 to your computer and use it in GitHub Desktop.
Save alanrsoares/11126970 to your computer and use it in GitHub Desktop.
A Pen by Alan R. Soares.
<div class='container' ng-app='evaluator'>
<div class='page-header'>
<h1>Math Expression Evaluator</h1>
</div>
<form role="form" ng-controller='AppCtrl' class='well'>
<div class="form-group">
<label for="expression">Expression</label>
<input class="form-control" id='expression' type='text' ng-model='expression' placeholder='enter expression' />
</div>
<div class="form-group">
<label for="result">Result</label>
<input type="text" disabled='disabled' ng-model='result' class="form-control alert-info" id="result" placeholder="result">
</div>
</form>
</div>
var app = angular.module('evaluator', [])
.controller('AppCtrl', function ($scope, expressionEvaluator) {
var ee = expressionEvaluator;
var onExpressionChange = function (newValue, oldValue) {
if (newValue !== oldValue && ee.isValid(ee.sanitize(newValue))) {
$scope.result = ee.evaluate(newValue);
}
};
(function init() {
$scope.$watch('expression', onExpressionChange);
$scope.expression = "3 ^ (3 + (1 + 2 - 3)) * 4 / 5";
$scope.result = ee.evaluate($scope.expression);
}());
})
.factory('expressionEvaluator', function () {
var mathPatt = /(\d+(\.\d+)?)([\^*\/\+-])(\d+(\.\d+)?)/;
var precPatt0 = /(\d+(\.\d+)?)(\^)(\d+(\.\d+)?)/;
var precPatt1 = /(\d+(\.\d+)?)([*\/])(\d+(\.\d+)?)/;
var subExprPatt = /\([\d\.\+\/-]+\)/;
function isValid(expr) {
return mathPatt.test(expr);
}
function sanitize(expr) {
return expr.trim().replace(/\s+/ig, '');
}
function getNextSegment(expr) {
return precPatt0.exec(expr) || precPatt1.exec(expr) || mathPatt.exec(expr);
}
function hasSubExpression(expr) {
return subExprPatt.test(expr);
}
function getSubExpression(expr) {
return subExprPatt.exec(expr);
}
function evaluateSegment(segment) {
var operator = segment[3];
var elm1 = parseFloat(segment[1]);
var elm2 = parseFloat(segment[4]);
console.log("evaluating segment: " + segment[0]);
switch (operator) {
case "^":
return Math.pow(elm1, elm2);
case "*":
return elm1 * elm2;
case "/":
return elm1 / elm2;
case "+":
return elm1 + elm2;
case "-":
return elm1 - elm2;
}
}
function replaceSegmentResult(segment, result) {
return segment.input.replace(segment[0], result.toString());
}
function evaluate(expression) {
var expr = sanitize(expression);
console.log("evaluating expression: " + expr);
var result;
while (hasSubExpression(expr)) {
var subExprSegment = getSubExpression(expr);
var subExpression = subExprSegment[0].replace(/[\(\)]/ig, '');
result = evaluate(subExpression);
expr = replaceSegmentResult(subExprSegment, result);
}
while (isValid(expr)) {
var segment = getNextSegment(expr);
result = evaluateSegment(segment);
expr = replaceSegmentResult(segment, result);
}
var res = parseFloat(expr);
console.log(res);
return res;
}
return {
evaluate: evaluate,
isValid: isValid,
sanitize: sanitize
};
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment