MCPcopy
hub / github.com/styled-components/polished / calculate

Function calculate

src/math/math.js:23–99  ·  view source on GitHub ↗
(expression: string, additionalSymbols?: Object)

Source from the content-addressed store, hash-verified

21}
22
23function calculate(expression: string, additionalSymbols?: Object): number {
24 const symbolMap = mergeSymbolMaps(additionalSymbols)
25
26 let match
27 const operators = [symbolMap.symbols['('].prefix]
28 const values = []
29
30 const pattern = new RegExp( // Pattern for numbers
31 `\\d+(?:\\.\\d+)?|${
32 // ...and patterns for individual operators/function names
33 Object.keys(symbolMap.symbols)
34 .map(key => symbolMap.symbols[key])
35 // longer symbols should be listed first
36 // $FlowFixMe
37 .sort((a, b) => b.symbol.length - a.symbol.length)
38 // $FlowFixMe
39 .map(val => val.regSymbol)
40 .join('|')
41 }|(\\S)`,
42 'g',
43 )
44 pattern.lastIndex = 0 // Reset regular expression object
45
46 let afterValue = false
47
48 do {
49 match = pattern.exec(expression)
50
51 const [token, bad] = match || [')', undefined]
52 const notNumber = symbolMap.symbols[token]
53 const notNewValue = notNumber && !notNumber.prefix && !notNumber.func
54 const notAfterValue = !notNumber || (!notNumber.postfix && !notNumber.infix)
55
56 // Check for syntax errors:
57 if (bad || (afterValue ? notAfterValue : notNewValue)) {
58 throw new PolishedError(37, match ? match.index : expression.length, expression)
59 }
60
61 if (afterValue) {
62 // We either have an infix or postfix operator (they should be mutually exclusive)
63 const curr = notNumber.postfix || notNumber.infix
64 do {
65 const prev = operators[operators.length - 1]
66 if ((curr.precedence - prev.precedence || prev.rightToLeft) > 0) break
67 // Apply previous operator, since it has precedence over current one
68 } while (exec(operators, values)) // Exit loop after executing an opening parenthesis or function
69 afterValue = curr.notation === 'postfix'
70 if (curr.symbol !== ')') {
71 operators.push(curr)
72 // Postfix always has precedence over any operator that follows after it
73 if (afterValue) exec(operators, values)
74 }
75 } else if (notNumber) {
76 // prefix operator or function
77 operators.push(notNumber.prefix || notNumber.func)
78 if (notNumber.func) {
79 // Require an opening parenthesis
80 match = pattern.exec(expression)

Callers 1

mathFunction · 0.70

Calls 2

mergeSymbolMapsFunction · 0.70
execFunction · 0.70

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…