Skip to content

Commit

Permalink
wip expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
Zhirkevich Alexander Y authored and Zhirkevich Alexander Y committed Jul 1, 2024
1 parent 5b2454a commit 008a61e
Show file tree
Hide file tree
Showing 8 changed files with 387 additions and 102 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ internal class ExpressionEvaluator(
val expr = statement.substringAfter("=")
}

private fun setValue(variable : String, value : Any) {

}

fun add(a : Any, b : Any) : Any {
return when {
a is Number && b is Number -> a.toFloat() + b.toFloat()
Expand Down
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
// }
//}
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")
}
}
}
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) {

}
}

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
}
}
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()
}
}
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
}
Loading

0 comments on commit 008a61e

Please sign in to comment.