(expression: string, get: (path: string) => any)
| 17 | } |
| 18 | |
| 19 | export function parseExpression(expression: string, get: (path: string) => any) { |
| 20 | const parsed = math.parse(expression) |
| 21 | const symbols = getSymbols(parsed) |
| 22 | const scope = symbols.reduce((acc, path) => { |
| 23 | const symbol = get(path) |
| 24 | if (!symbol) throw Error(`Invalid symbol at path \`${path}\``) |
| 25 | return Object.assign(acc, { [path]: symbol }) |
| 26 | }, {} as { [key in keyof typeof symbols]: any }) |
| 27 | |
| 28 | let _formattedString = parsed.toString() |
| 29 | |
| 30 | for (let key in scope) { |
| 31 | const re = new RegExp(`\\b${key}\\b`, 'g') |
| 32 | // TODO check type better than this |
| 33 | const s = typeof scope[key] === 'function' ? scope[key].__parsedScoped.toString() : scope[key] |
| 34 | _formattedString = _formattedString.replace(re, s) |
| 35 | } |
| 36 | |
| 37 | const parsedScoped = math.parse(_formattedString) |
| 38 | const compiled = parsedScoped.compile() |
| 39 | |
| 40 | function expr(v: number) { |
| 41 | return compiled.evaluate({ x: v }) |
| 42 | } |
| 43 | |
| 44 | Object.assign(expr, { |
| 45 | __parsedScoped: parsedScoped, |
| 46 | __parsed: parsed, |
| 47 | __symbols: symbols, |
| 48 | }) |
| 49 | |
| 50 | return expr |
| 51 | } |
no test coverage detected
searching dependent graphs…