-
Notifications
You must be signed in to change notification settings - Fork 0
/
parse.js
61 lines (56 loc) · 2.14 KB
/
parse.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/*
* uses regex groups for match destructuring
* parentheses: between parentheses, match any character except parentheses
* exponent: matches positive and negative exponents, not fractional exponents
* +,-,*,/: matches negative and decimal numbers
*/
const PARENTHESES_REGEX = /\((?<equation>[^\(\)]*)\)/
const EXPONENT_REGEX = /(?<operand1>-?\d*\.?\d+)(?<operation>\^)(?<operand2>-?\d+)/
const MULTIPLY_DIVIDE_REGEX = /(?<operand1>-?\d*\.?\d+)(?<operation>[\*\/])(?<operand2>-?\d*\.?\d+)/
const ADD_SUBTRACT_REGEX = /(?<operand1>-?\d*\.?\d+)(?<operation>[-\+])(?<operand2>-?\d*\.?\d+)/
const FRACTIONAL_EXPONENT_REGEX = /\^\d*\.+/
export default function solve(eq) {
const equation = eq.replace(/\s/g, '')
return parse(equation)
}
function parse(equation) {
if (equation.match(PARENTHESES_REGEX)) {
const subEquation = equation.match(PARENTHESES_REGEX).groups.equation
const result = parse(subEquation)
const newEquation = equation.replace(PARENTHESES_REGEX, result)
return parse(newEquation)
} else if (equation.match(EXPONENT_REGEX)) {
if (equation.match(FRACTIONAL_EXPONENT_REGEX)) return NaN
const result = doMath(equation.match(EXPONENT_REGEX).groups)
const newEquation = equation.replace(EXPONENT_REGEX, result)
return parse(newEquation)
} else if (equation.match(MULTIPLY_DIVIDE_REGEX)) {
const result = doMath(equation.match(MULTIPLY_DIVIDE_REGEX).groups)
const newEquation = equation.replace(MULTIPLY_DIVIDE_REGEX, result)
return parse(newEquation)
} else if (equation.match(ADD_SUBTRACT_REGEX)) {
const result = doMath(equation.match(ADD_SUBTRACT_REGEX).groups)
const newEquation = equation.replace(ADD_SUBTRACT_REGEX, result)
return parse(newEquation)
} else if (isNaN(equation)) {
return NaN
} else {
return parseFloat(equation)
}
}
function doMath({ operand1, operand2, operation }) {
const num1 = parseFloat(operand1)
const num2 = parseFloat(operand2)
switch (operation) {
case '*':
return num1 * num2
case '/':
return num1 / num2
case '+':
return num1 + num2
case '-':
return num1 - num2
case '^':
return num1 ** num2
}
}