Swiftpack.co is a collection of thousands of indexed Swift packages. Search packages.

See all packages published by bradhowes.

bradhowes/swift-math-parser 2.1.2

Math expression parser built with Point•Free's swift-parsing package

⭐️ 29

🕓 1 week ago

iOS
macOS
watchOS
tvOS

.package(url: "https://github.com/bradhowes/swift-math-parser.git", from: "2.1.2")

Basic math expression parser built with Point•Free's swift-parsing package (v0.10.0).

```
let parser = MathParser()
let evaluator = parser.parse('4 × sin(t × π) + 2 × sin(t × π)')
evaluator.eval("t", value: 0.0) // => 0.0
evaluator.eval("t", value: 0.25) // => 4.2426406871192848
evaluator.eval("t", value: 0.5) // => 6
evaluator.eval("t", value: 1.0) // => 0
```

The parser will return `nil`

if it is unable to completely parse the expression.

By default, the expression parser and evaluator handle the following symbols and functions:

- Constants:
`pi`

(`π`

) and`e`

- 1-argument functions:
`sin`

,`cos`

,`tan`

,`log10`

,`ln`

(`loge`

),`log2`

,`exp`

,`ceil`

,`floor`

,`round`

,`sqrt`

(`√`

) - 2-argument functions:
`atan`

,`hypot`

,`pow`

[^1] - alternative math operator symbols:
`×`

for multiplication and`÷`

for division (see example above for use of`×`

)

You can reference additional symbols or variables and functions by providing your own mapping functions. There are two places where this can be done:

`MathParser.init`

`MathParser.Evaluator.eval`

If a symbol or function does not exist during an `eval`

call, the final result will be `NaN`

. If a symbol is resolved
during parsing, it will be replaced with the symbol's value. Otherwise, it will be resolved during a future `eval`

call.
Same for function calls -- if the function is known during parsing *and* all arguments have a known value, then it will
be replaced with the function result. Otherwise, the function call will take place during an `eval`

call.

Example:

```
let mySymbols = ["foo": 123.4]
let myFuncs: [String:(Double)->Double] = ["twice": {$0 + $0}]
let parser = MathParser(symbols: mySymbols.producer, unaryFunctions: myFuncs.producer)
let myEvalFuncs: [String:(Double)->Double] = ["power": {$0 * $0}]
let evaluator = parser.parse("power(twice(foo))")
# Expression parsed and `twice(foo)` resolved to `246.8` but `power` is still unknown
evaluator?.value // => nan
# Give evaluator way to resolve `power(246.8)`
evaluator?.eval(unaryFunctions: myEvalFuncs.producer) // => 60910.240000000005
```

One of the original goals of this parser was to be able to accept a Wolfram Alpha math expression more or less as-is -- for instance the definition https://www.wolframalpha.com/input/?i=Sawsbuck+Winter+Form%E2%80%90like+curve -- without any editing. Here is the start of the textual representation from the above link:

```
x(t) = ((-2/9 sin(11/7 - 4 t) + 78/11 sin(t + 11/7) + 2/7 sin(2 t + 8/5) ...
```

Skipping over the assignment one can readily see that the representation includes implied multiplication between terms
when there are no explicit math operators present (eg `-2/9`

**x** `sin(11/7 - 4`

**x** `t)`

). There is support for this
sort of operation in the parser that can be enabled by setting `enableImpliedMultiplication`

when creating a new
`MathParser`

instance (it defaults to `false`

). Note that when enabled, an expression such as `2^3 2^4`

would be
considered a valid expression, resolving to `2^3 * 2^4 = 128`

, and `4sin(t(pi))`

would become `4 * sin(t * pi)`

.

Here is the original example expression with implied multiplication:

```
let parser = MathParser(enableImpliedMultiplication: true)
let evaluator = parser.parse("4sin(t π) + 2sin(t π)")
evaluator.eval("t", value: 0.0) // => 0.0
evaluator.eval("t", value: 0.25) // => 4.2426406871192848
evaluator.eval("t", value: 0.5) // => 6
evaluator.eval("t", value: 1.0) // => 0
```

Note that `t π`

cannot be `tπ`

since the parser treats the latter as one symbol and not two.

[^1]: Redundant since there is already the `^`

operator.

link |

Stars: 29 |

Last commit: 1 week ago |

Time Bandits

1 week ago

Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API | Analytics