-
Notifications
You must be signed in to change notification settings - Fork 1
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
0 parents
commit bd43e44
Showing
104 changed files
with
2,830 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
.gradle | ||
build | ||
.idea | ||
.kotlin | ||
.DS_Store | ||
/gradle/wrapper/gradle-wrapper.jar |
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,83 @@ | ||
# Calkt | ||
|
||
Calkt is a Kotlin library that supports parsing and calculating | ||
various expressions. Parser is written in a way to have an ability | ||
to be extended. | ||
|
||
<!-- TOC --> | ||
* [Calkt](#calkt) | ||
* [Example](#example) | ||
* [Implementation](#implementation) | ||
* [Modules](#modules) | ||
* [core](#core) | ||
* [math](#math) | ||
* [units](#units) | ||
* [example](#example-1) | ||
<!-- TOC --> | ||
|
||
## Example | ||
|
||
The result of running [example/Main.kt](example/src/main/kotlin/Main.kt): | ||
|
||
```text | ||
Enter math expression to calculate: 2 + 2 * 2 | ||
Parsed as: 2 plus (2 times 2) | ||
Result: 6 | ||
Enter an expression with units to calculate: (1km - 0.5mi) + 2 yd to inches | ||
Parsed as: (((1 Kilometers) minus (0.5 Miles)) plus (2 Yards)).convert(Inches) | ||
Result: 7886.272 Inches | ||
``` | ||
|
||
## Implementation | ||
|
||
Work In Progress. Will be available at maven central soon. | ||
Now you can use workarounds like [jitpack.io](https://jitpack.io/#y9san9/calkt/-SNAPSHOT): | ||
|
||
Add Jitpack repo in the root build.gradle at the end of repositories: | ||
|
||
```kotlin | ||
dependencyResolutionManagement { | ||
repositories { | ||
mavenCentral() | ||
maven("https://jitpack.io") | ||
} | ||
} | ||
``` | ||
|
||
Step 2. Add the dependency | ||
```kotlin | ||
dependencies { | ||
implementation("com.github.y9san9:calkt:-SNAPSHOT") | ||
} | ||
``` | ||
|
||
## Modules | ||
|
||
The library consists of several different modules: | ||
|
||
### core | ||
|
||
Module with all basic types for parsing and calculating. Here | ||
you can find `ParseContext` and `CalculateContext` as well as | ||
functions to launch parsers/calculators. | ||
|
||
### math | ||
|
||
Module with implementation of basic math expressions that any | ||
calculator can calculate. This is where you can find logic to | ||
calculate numbers combined with basic supported operators ( | ||
`+`, `-`, `*`, `/`). You can implement your own operator, like | ||
in [this example](example/src/main/kotlin/operator/ModOperator.kt) (% operator). | ||
|
||
### units | ||
|
||
Module with implementation of math expressions with units. It | ||
depends on `math` module heavily and does not do any calculations | ||
on its own. There is a logic to support calculation and | ||
conversions of units like `1 km + 2`, `1km to inches`, etc. | ||
|
||
### example | ||
|
||
Module with all the examples you need to know. If something is missing, | ||
PRs are welcome. |
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,7 @@ | ||
plugins { | ||
`kotlin-dsl` | ||
} | ||
|
||
dependencies { | ||
api(libs.kotlin.gradle.plugin) | ||
} |
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,12 @@ | ||
dependencyResolutionManagement { | ||
repositories { | ||
mavenCentral() | ||
google() | ||
} | ||
|
||
versionCatalogs { | ||
create("libs") { | ||
from(files("../gradle/libs.versions.toml")) | ||
} | ||
} | ||
} |
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,26 @@ | ||
import org.gradle.api.Project | ||
|
||
fun Project.versionFromProperties(acceptor: (String) -> Unit) { | ||
afterEvaluate { | ||
acceptor(versionFromProperties()) | ||
} | ||
} | ||
|
||
fun Project.versionFromProperties(): String { | ||
val snapshot = project.findProperty("snapshot")?.toString()?.toBooleanStrict() | ||
if (snapshot == null || !snapshot) return project.version.toString() | ||
|
||
val commit = project.property("commit").toString() | ||
val attempt = project.property("attempt").toString().toInt() | ||
|
||
val version = buildString { | ||
append(project.version) | ||
append("-build") | ||
append(commit.take(n = 7)) | ||
if (attempt > 1) { | ||
append(attempt) | ||
} | ||
} | ||
|
||
return version | ||
} |
25 changes: 25 additions & 0 deletions
25
build-logic/src/main/kotlin/kmp-library-convention.gradle.kts
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,25 @@ | ||
plugins { | ||
kotlin("multiplatform") | ||
id("publication-convention") | ||
} | ||
|
||
kotlin { | ||
compilerOptions { | ||
allWarningsAsErrors = true | ||
progressiveMode = true | ||
} | ||
|
||
explicitApi() | ||
|
||
jvmToolchain(17) | ||
|
||
jvm() | ||
|
||
js(IR) { | ||
browser() | ||
nodejs() | ||
} | ||
iosArm64() | ||
iosX64() | ||
iosSimulatorArm64() | ||
} |
11 changes: 11 additions & 0 deletions
11
build-logic/src/main/kotlin/print-version-convention.gradle.kts
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,11 @@ | ||
import org.gradle.kotlin.dsl.creating | ||
|
||
tasks { | ||
val printVersion by creating { | ||
group = "CI" | ||
|
||
doFirst { | ||
println(versionFromProperties()) | ||
} | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
build-logic/src/main/kotlin/publication-convention.gradle.kts
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,24 @@ | ||
plugins { | ||
id("org.gradle.maven-publish") | ||
} | ||
|
||
group = "app.meetacy.ksm" | ||
|
||
publishing { | ||
repositories { | ||
maven { | ||
name = "GitHub" | ||
url = uri("https://maven.pkg.github.com/meetacy/ksm") | ||
credentials { | ||
username = System.getenv("GITHUB_USERNAME") | ||
password = System.getenv("GITHUB_TOKEN") | ||
} | ||
} | ||
} | ||
|
||
publications.withType<MavenPublication> { | ||
versionFromProperties { version -> | ||
this.version = version | ||
} | ||
} | ||
} |
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,21 @@ | ||
plugins { | ||
kotlin("jvm") version "2.0.0" | ||
} | ||
|
||
group = "me.y9san9" | ||
version = "1.0-SNAPSHOT" | ||
|
||
repositories { | ||
mavenCentral() | ||
} | ||
|
||
dependencies { | ||
testImplementation(kotlin("test")) | ||
} | ||
|
||
tasks.test { | ||
useJUnitPlatform() | ||
} | ||
kotlin { | ||
jvmToolchain(17) | ||
} |
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 @@ | ||
plugins { | ||
id("kmp-library-convention") | ||
} | ||
|
||
dependencies { | ||
commonMainImplementation(libs.bignum) | ||
commonTestImplementation(projects.math) | ||
commonTestImplementation(projects.units) | ||
} |
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 @@ | ||
@file:OptIn(ExperimentalSubclassOptIn::class) | ||
|
||
package me.y9san9.calkt | ||
|
||
import me.y9san9.calkt.annotation.ExpressionSubclass | ||
|
||
@SubclassOptInRequired(ExpressionSubclass::class) | ||
public interface Expression |
7 changes: 7 additions & 0 deletions
7
core/src/commonMain/kotlin/me/y9san9/calkt/annotation/CalculateSubclass.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,7 @@ | ||
package me.y9san9.calkt.annotation | ||
|
||
@RequiresOptIn( | ||
message = "Usage of CalculateResult type is heavily dependent on knowledge of all subclasses. " + | ||
"So when you subclass CalculateResult those places might brake, be careful", | ||
) | ||
public annotation class CalculateSubclass |
7 changes: 7 additions & 0 deletions
7
core/src/commonMain/kotlin/me/y9san9/calkt/annotation/ExpressionSubclass.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,7 @@ | ||
package me.y9san9.calkt.annotation | ||
|
||
@RequiresOptIn( | ||
message = "Usage of Expression type is heavily dependent on knowledge of all subclasses. " + | ||
"So when you subclass Expression those places might brake, be careful", | ||
) | ||
public annotation class ExpressionSubclass |
7 changes: 7 additions & 0 deletions
7
core/src/commonMain/kotlin/me/y9san9/calkt/annotation/FailureCauseSubclass.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,7 @@ | ||
package me.y9san9.calkt.annotation | ||
|
||
@RequiresOptIn( | ||
message = "Usage of FailureCause type is heavily dependent on knowledge of all subclasses. " + | ||
"So when you subclass FailureCause those places might brake, be careful", | ||
) | ||
public annotation class FailureCauseSubclass |
54 changes: 54 additions & 0 deletions
54
core/src/commonMain/kotlin/me/y9san9/calkt/calculate/CalculateContext.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,54 @@ | ||
package me.y9san9.calkt.calculate | ||
|
||
import me.y9san9.calkt.Expression | ||
|
||
public class CalculateContext( | ||
public val expression: Expression, | ||
public val calculateFunction: CalculateFunction, | ||
public val precision: Long | ||
) { | ||
public val context: CalculateContext get() = this | ||
|
||
public fun tryCalculate(function: CalculateFunction): CalculateResult { | ||
return tryCalculate(expression, precision, function, calculateFunction) | ||
} | ||
|
||
public fun recursive(expression: Expression): CalculateResult.Success { | ||
val context = CalculateContext(expression, calculateFunction, precision) | ||
return calculateFunction(context) | ||
} | ||
|
||
public fun unsupportedExpression(): Nothing { | ||
fail(CalculateResult.UnsupportedExpression) | ||
} | ||
|
||
public fun fail( | ||
failure: CalculateResult.Failure | ||
): Nothing { | ||
throw FailureException(failure) | ||
} | ||
|
||
public class FailureException(public val failure: CalculateResult.Failure) : Throwable() | ||
} | ||
|
||
public fun tryCalculate( | ||
expression: Expression, | ||
precision: Long, | ||
function: CalculateFunction | ||
): CalculateResult { | ||
return tryCalculate(expression, precision, function, function) | ||
} | ||
|
||
public fun tryCalculate( | ||
expression: Expression, | ||
precision: Long, | ||
function: CalculateFunction, | ||
recursive: CalculateFunction | ||
): CalculateResult { | ||
return try { | ||
val context = CalculateContext(expression, recursive, precision) | ||
function(context) | ||
} catch (exception: CalculateContext.FailureException) { | ||
exception.failure | ||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
core/src/commonMain/kotlin/me/y9san9/calkt/calculate/CalculateFunction.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,5 @@ | ||
package me.y9san9.calkt.calculate | ||
|
||
public fun interface CalculateFunction { | ||
public operator fun invoke(context: CalculateContext): CalculateResult.Success | ||
} |
28 changes: 28 additions & 0 deletions
28
core/src/commonMain/kotlin/me/y9san9/calkt/calculate/CalculateFunctionPlus.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,28 @@ | ||
package me.y9san9.calkt.calculate | ||
|
||
import me.y9san9.calkt.calculate.CalculateResult.UnsupportedExpression | ||
|
||
private class CombinedCalculateFunction( | ||
val functions: List<CalculateFunction> | ||
) : CalculateFunction { | ||
override fun invoke(context: CalculateContext): CalculateResult.Success { | ||
for (function in functions) { | ||
val result = context.tryCalculate(function) | ||
if (result is UnsupportedExpression) continue | ||
return result.getOrFail(context) | ||
} | ||
context.unsupportedExpression() | ||
} | ||
} | ||
|
||
public operator fun CalculateFunction.plus( | ||
other: CalculateFunction | ||
): CalculateFunction { | ||
val functions = when { | ||
this is CombinedCalculateFunction && other is CombinedCalculateFunction -> this.functions + other.functions | ||
this is CombinedCalculateFunction -> this.functions + other | ||
other is CombinedCalculateFunction -> listOf(this) + other.functions | ||
else -> listOf(this, other) | ||
} | ||
return CombinedCalculateFunction(functions) | ||
} |
26 changes: 26 additions & 0 deletions
26
core/src/commonMain/kotlin/me/y9san9/calkt/calculate/CalculateResult.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,26 @@ | ||
package me.y9san9.calkt.calculate | ||
|
||
import me.y9san9.calkt.annotation.CalculateSubclass | ||
|
||
public sealed interface CalculateResult { | ||
@OptIn(ExperimentalSubclassOptIn::class) | ||
@SubclassOptInRequired(CalculateSubclass::class) | ||
public interface Failure : CalculateResult | ||
|
||
@OptIn(CalculateSubclass::class) | ||
public data object UnsupportedExpression : Failure | ||
|
||
@OptIn(CalculateSubclass::class) | ||
public data object DivisionByZero : Failure | ||
|
||
@OptIn(ExperimentalSubclassOptIn::class) | ||
@SubclassOptInRequired(CalculateSubclass::class) | ||
public interface Success : CalculateResult | ||
} | ||
|
||
public fun CalculateResult.getOrFail(context: CalculateContext): CalculateResult.Success { | ||
return when (this) { | ||
is CalculateResult.Failure -> context.fail(failure = this) | ||
is CalculateResult.Success -> this | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
core/src/commonMain/kotlin/me/y9san9/calkt/internal/StringBuilder.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,10 @@ | ||
package me.y9san9.calkt.internal | ||
|
||
@PublishedApi | ||
internal inline fun StringBuilder.withIndent( | ||
indent: String = " ", | ||
block: StringBuilder.() -> Unit | ||
) { | ||
val string = buildString(block).prependIndent(indent) | ||
append(string) | ||
} |
Oops, something went wrong.