-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Zhirkevich Alexander Y
authored and
Zhirkevich Alexander Y
committed
Jul 1, 2024
1 parent
5b2454a
commit 008a61e
Showing
8 changed files
with
387 additions
and
102 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
204 changes: 102 additions & 102 deletions
204
...mmonMain/kotlin/io/github/alexzhirkevich/compottie/internal/animation/expressions/eval.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,102 +1,102 @@ | ||
package io.github.alexzhirkevich.compottie.internal.animation.expressions | ||
|
||
import kotlin.math.PI | ||
import kotlin.math.cos | ||
import kotlin.math.ln | ||
import kotlin.math.pow | ||
import kotlin.math.sin | ||
import kotlin.math.sqrt | ||
import kotlin.math.tan | ||
|
||
fun eval(str: String): Double { | ||
return Evaluator(str).parse() | ||
} | ||
|
||
private class Evaluator(private val expr : String) { | ||
var pos = -1 | ||
var ch = 0 | ||
fun nextChar() { | ||
ch = if (++pos < expr.length) expr[pos].code else -1 | ||
} | ||
|
||
fun eat(charToEat: Int): Boolean { | ||
while (ch == ' '.code) nextChar() | ||
if (ch == charToEat) { | ||
nextChar() | ||
return true | ||
} | ||
return false | ||
} | ||
|
||
fun parse(): Double { | ||
nextChar() | ||
val x = parseExpression() | ||
if (pos < expr.length) throw IllegalArgumentException("Unexpected: " + ch.toChar()) | ||
return x | ||
} | ||
|
||
// Grammar: | ||
// expression = term | expression `+` term | expression `-` term | ||
// term = factor | term `*` factor | term `/` factor | ||
// factor = `+` factor | `-` factor | `(` expression `)` | number | ||
// | functionName `(` expression `)` | functionName factor | ||
// | factor `^` factor | ||
fun parseExpression(): Double { | ||
var x = parseTerm() | ||
while (true) { | ||
if (eat('+'.code)) x += parseTerm() // addition | ||
else if (eat('-'.code)) x -= parseTerm() // subtraction | ||
else return x | ||
} | ||
} | ||
|
||
fun parseTerm(): Double { | ||
var x = parseFactor() | ||
while (true) { | ||
if (eat('*'.code)) x *= parseFactor() // multiplication | ||
else if (eat('/'.code)) x /= parseFactor() // division | ||
else return x | ||
} | ||
} | ||
|
||
fun parseFactor(): Double { | ||
if (eat('+'.code)) return +parseFactor() // unary plus | ||
if (eat('-'.code)) return -parseFactor() // unary minus | ||
var x: Double | ||
val startPos = pos | ||
if (eat('('.code)) { // parentheses | ||
x = parseExpression() | ||
if (!eat(')'.code)) throw IllegalArgumentException("Missing ')'") | ||
} else if (ch >= '0'.code && ch <= '9'.code || ch == '.'.code) { // numbers | ||
while (ch >= '0'.code && ch <= '9'.code || ch == '.'.code) nextChar() | ||
x = expr.substring(startPos, pos).toDouble() | ||
} else if (ch >= 'a'.code && ch <= 'z'.code) { // functions | ||
while (ch >= 'a'.code && ch <= 'z'.code) nextChar() | ||
val func = expr.substring(startPos, pos) | ||
if (eat('('.code)) { | ||
x = parseExpression() | ||
if (!eat(')'.code)) throw IllegalArgumentException("Missing ')' after argument to $func") | ||
} else { | ||
x = parseFactor() | ||
} | ||
x = when (func) { | ||
"sqrt" -> sqrt(x) | ||
"sin" -> sin(toRadians(x)) | ||
"cos" -> cos(toRadians(x)) | ||
"tan" -> tan(toRadians(x)) | ||
"ln" -> ln(x) | ||
else -> throw IllegalArgumentException( | ||
"Unknown function: $func" | ||
) | ||
} | ||
} else { | ||
throw IllegalArgumentException("Unexpected: " + ch.toChar()) | ||
} | ||
if (eat('^'.code)) x = x.pow(parseFactor()) // exponentiation | ||
return x | ||
} | ||
|
||
fun toRadians(degree: Double): Double { | ||
return degree * PI / 180 | ||
} | ||
} | ||
//package io.github.alexzhirkevich.compottie.internal.animation.expressions | ||
// | ||
//import kotlin.math.PI | ||
//import kotlin.math.cos | ||
//import kotlin.math.ln | ||
//import kotlin.math.pow | ||
//import kotlin.math.sin | ||
//import kotlin.math.sqrt | ||
//import kotlin.math.tan | ||
// | ||
//fun eval(str: String): Double { | ||
// return Evaluator(str).parse() | ||
//} | ||
// | ||
//private class Evaluator(private val expr : String) { | ||
// var pos = -1 | ||
// var ch = 0 | ||
// fun nextChar() { | ||
// ch = if (++pos < expr.length) expr[pos].code else -1 | ||
// } | ||
// | ||
// fun eat(charToEat: Int): Boolean { | ||
// while (ch == ' '.code) nextChar() | ||
// if (ch == charToEat) { | ||
// nextChar() | ||
// return true | ||
// } | ||
// return false | ||
// } | ||
// | ||
// fun parse(): Double { | ||
// nextChar() | ||
// val x = parseExpression() | ||
// if (pos < expr.length) throw IllegalArgumentException("Unexpected: " + ch.toChar()) | ||
// return x | ||
// } | ||
// | ||
// // Grammar: | ||
// // expression = term | expression `+` term | expression `-` term | ||
// // term = factor | term `*` factor | term `/` factor | ||
// // factor = `+` factor | `-` factor | `(` expression `)` | number | ||
// // | functionName `(` expression `)` | functionName factor | ||
// // | factor `^` factor | ||
// fun parseExpression(): Double { | ||
// var x = parseTerm() | ||
// while (true) { | ||
// if (eat('+'.code)) x += parseTerm() // addition | ||
// else if (eat('-'.code)) x -= parseTerm() // subtraction | ||
// else return x | ||
// } | ||
// } | ||
// | ||
// fun parseTerm(): Double { | ||
// var x = parseFactor() | ||
// while (true) { | ||
// if (eat('*'.code)) x *= parseFactor() // multiplication | ||
// else if (eat('/'.code)) x /= parseFactor() // division | ||
// else return x | ||
// } | ||
// } | ||
// | ||
// fun parseFactor(): Double { | ||
// if (eat('+'.code)) return +parseFactor() // unary plus | ||
// if (eat('-'.code)) return -parseFactor() // unary minus | ||
// var x: Double | ||
// val startPos = pos | ||
// if (eat('('.code)) { // parentheses | ||
// x = parseExpression() | ||
// if (!eat(')'.code)) throw IllegalArgumentException("Missing ')'") | ||
// } else if (ch >= '0'.code && ch <= '9'.code || ch == '.'.code) { // numbers | ||
// while (ch >= '0'.code && ch <= '9'.code || ch == '.'.code) nextChar() | ||
// x = expr.substring(startPos, pos).toDouble() | ||
// } else if (ch >= 'a'.code && ch <= 'z'.code) { // functions | ||
// while (ch >= 'a'.code && ch <= 'z'.code) nextChar() | ||
// val func = expr.substring(startPos, pos) | ||
// if (eat('('.code)) { | ||
// x = parseExpression() | ||
// if (!eat(')'.code)) throw IllegalArgumentException("Missing ')' after argument to $func") | ||
// } else { | ||
// x = parseFactor() | ||
// } | ||
// x = when (func) { | ||
// "sqrt" -> sqrt(x) | ||
// "sin" -> sin(toRadians(x)) | ||
// "cos" -> cos(toRadians(x)) | ||
// "tan" -> tan(toRadians(x)) | ||
// "ln" -> ln(x) | ||
// else -> throw IllegalArgumentException( | ||
// "Unknown function: $func" | ||
// ) | ||
// } | ||
// } else { | ||
// throw IllegalArgumentException("Unexpected: " + ch.toChar()) | ||
// } | ||
// if (eat('^'.code)) x = x.pow(parseFactor()) // exponentiation | ||
// return x | ||
// } | ||
// | ||
// fun toRadians(degree: Double): Double { | ||
// return degree * PI / 180 | ||
// } | ||
//} |
22 changes: 22 additions & 0 deletions
22
...github/alexzhirkevich/compottie/internal/animation/expressions/operations/AddOperation.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package io.github.alexzhirkevich.compottie.internal.animation.expressions.operations | ||
|
||
import io.github.alexzhirkevich.compottie.internal.AnimationState | ||
import io.github.alexzhirkevich.compottie.internal.animation.Vec2 | ||
|
||
internal class AddOperation( | ||
val a : Operation, | ||
val b : Operation | ||
) : Operation { | ||
|
||
override fun invoke(value : Any, state: AnimationState): Any { | ||
val a = a(value, state) | ||
val b = b(value, state) | ||
|
||
return when { | ||
a is Float && b is Float -> a + b | ||
a is Vec2 && b is Vec2 -> a + b | ||
|
||
else -> error("Cant calculate the sum of $a and $b") | ||
} | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
...o/github/alexzhirkevich/compottie/internal/animation/expressions/operations/Expression.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package io.github.alexzhirkevich.compottie.internal.animation.expressions.operations | ||
|
||
import io.github.alexzhirkevich.compottie.internal.AnimationState | ||
|
||
internal class Expression( | ||
val variables : Map<String, Any>, | ||
val expression : String | ||
) { | ||
|
||
operator fun invoke(state: AnimationState) { | ||
|
||
} | ||
} | ||
|
9 changes: 9 additions & 0 deletions
9
...b/alexzhirkevich/compottie/internal/animation/expressions/operations/GetValueOperation.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package io.github.alexzhirkevich.compottie.internal.animation.expressions.operations | ||
|
||
import io.github.alexzhirkevich.compottie.internal.AnimationState | ||
|
||
internal class GetValueOperation : Operation { | ||
override fun invoke(value: Any, state: AnimationState): Any { | ||
return value | ||
} | ||
} |
41 changes: 41 additions & 0 deletions
41
...kotlin/io/github/alexzhirkevich/compottie/internal/animation/expressions/operations/Op.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package io.github.alexzhirkevich.compottie.internal.animation.expressions.operations | ||
|
||
import io.github.alexzhirkevich.compottie.internal.animation.Vec2 | ||
|
||
object Op { | ||
|
||
fun sum(a : Any, b : Any) : Any { | ||
return when { | ||
a is Float && b is Float -> a + b | ||
a is Vec2 && b is Vec2 -> a + b | ||
|
||
else -> error("Cant calculate the sum of $a and $b") | ||
} | ||
} | ||
|
||
|
||
fun sub(a : Any, b : Any) : Any { | ||
TODO() | ||
} | ||
|
||
fun mul(a : Any, b : Any) : Any { | ||
TODO() | ||
} | ||
|
||
fun div(a : Any, b : Any) : Any { | ||
TODO() | ||
} | ||
|
||
fun sqrt(a : Any) : Any { | ||
TODO() | ||
} | ||
fun sin(a : Any) : Any { | ||
TODO() | ||
} | ||
fun cos(a : Any) : Any { | ||
TODO() | ||
} | ||
fun mod(a : Any, b : Any) : Any { | ||
TODO() | ||
} | ||
} |
8 changes: 8 additions & 0 deletions
8
...io/github/alexzhirkevich/compottie/internal/animation/expressions/operations/Operation.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package io.github.alexzhirkevich.compottie.internal.animation.expressions.operations | ||
|
||
import io.github.alexzhirkevich.compottie.internal.AnimationState | ||
|
||
internal fun interface Operation { | ||
|
||
operator fun invoke(value : Any, state: AnimationState) : Any | ||
} |
Oops, something went wrong.