Skip to content

Instantly share code, notes, and snippets.

@think49
Last active November 13, 2016 15:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save think49/3c484937a84c91cd5c51f5788c7c34c7 to your computer and use it in GitHub Desktop.
Save think49/3c484937a84c91cd5c51f5788c7c34c7 to your computer and use it in GitHub Desktop.
calculation-sample.js: LLmanさんのアドバイスを元に書いたコード。SyntaxErrorのエラー検出処理と数値演算処理を別関数に分割した。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>calculation-sample.js</title>
<script>
/**
* calculation-sample.js
* evaluate calculation formula.
*
* @version 0.1.1
* @author think49
* @url https://gist.github.com/think49/3c484937a84c91cd5c51f5788c7c34c7
* @license http://www.opensource.org/licenses/mit-license.php (The MIT License)
*/
'use strict';
var Calculation = (function (String, pow, max) {
'use strict';
function getDecimalPartLength (numberString) {
var result = /\.\d+$/.exec(numberString);
return result ? result[0].length - 1 : 0;
}
function calcDyadicOperator (matched, number1, operator, number2) {
var decimalPart = /\.\d+$/, powerNumber1, powerNumber2, result;
switch (operator) {
case '+':
powerNumber1 = pow(10, max(getDecimalPartLength(number1), getDecimalPartLength(number2)));
result = (powerNumber1 * number1 + powerNumber1 * number2) / powerNumber1;
break;
case '-':
powerNumber1 = pow(10, max(getDecimalPartLength(number1), getDecimalPartLength(number2)));
result = (powerNumber1 * number1 - powerNumber1 * number2) / powerNumber1;
break;
case '*':
powerNumber1 = pow(10, getDecimalPartLength(number1));
powerNumber2 = pow(10, getDecimalPartLength(number2));
result = (number1 * powerNumber1) * (number2 * powerNumber2) / (powerNumber1 * powerNumber2);
break;
case '/':
powerNumber1 = pow(10, max(getDecimalPartLength(number1), getDecimalPartLength(number2)));
result = (number1 * powerNumber1) / (number2 * powerNumber1);
break;
default:
console.warn('expression: ' + number1 + operator + number2);
throw new Error(operator + ' is not a operator');
}
// console.log(String(number1) + operator + number2 + '=' + result);
return result;
}
return {
eval: function _eval (expression) {
var multiplyOrDivide = /(-?(?:\d+(?:\.\d+)?|\.\d+))([*/])(-?(?:\d+(?:\.\d+)?|\.\d+))/g,
addOrSubtract = /(-?(?:\d+(?:\.\d+)?|\.\d+))([+-])(-?(?:\d+(?:\.\d+)?|\.\d+))/g;
while (multiplyOrDivide.test(expression)) {
expression = expression.replace(multiplyOrDivide, calcDyadicOperator);
}
while (addOrSubtract.test(expression)) {
expression = expression.replace(addOrSubtract, calcDyadicOperator);
}
return +expression;
},
checkSyntax: function checkSyntax (expression) {
var errors = [], illegalString;
expression = String(expression).replace(/\s+/g, '');
if (illegalString = /^[+-]?(?:\.[^\d]|[^\d.+-])/.exec(expression)) {
errors.push(new SyntaxError('An expression starts with an unexpected token: ' + illegalString[0]));
}
if (illegalString = /[^\d]$/.exec(expression)) {
errors.push(new SyntaxError('An expression ends with an unexpected token: ' + illegalString[0]));
}
if (illegalString = /\d*(?:\.\d*){2,}/.exec(expression)) {
errors.push(new SyntaxError('Illegal number: ' + illegalString[0]));
}
return errors;
}
};
}(String, Math.pow, Math.max));
</script>
</head>
<body>
<ul>
<li><a href="https://teratail.com/questions/54897#r88052">JavaScript - エラーメッセージをまとめて出力する為の最適解は?(54897)|teratail</a></li>
</ul>
<script>
'use strict';
console.log(Calculation.eval('/1.1.1*')); // NaN
console.log(Calculation.checkSyntax('/1.1.1*')); // [new SyntaxError('An expression starts with an unexpected token: /'), new SyntaxError('An expression ends with an unexpected token: *'), new SyntaxError('Illegal number: 1.1.1')]
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment