[orx-expression-evaluator] Switch to antlr-kotlin for parser generation and make it a common kotlin module
This commit is contained in:
@@ -19,6 +19,7 @@ libfreenect = "0.5.7-1.5.9"
|
|||||||
librealsense = "2.53.1-1.5.9"
|
librealsense = "2.53.1-1.5.9"
|
||||||
gson = "2.10.1"
|
gson = "2.10.1"
|
||||||
antlr = "4.13.1"
|
antlr = "4.13.1"
|
||||||
|
antlrKotlin = "0.1.0-RC14"
|
||||||
tensorflow = "0.5.0"
|
tensorflow = "0.5.0"
|
||||||
minim = "2.2.2"
|
minim = "2.2.2"
|
||||||
netty = "4.1.92.Final"
|
netty = "4.1.92.Final"
|
||||||
@@ -76,6 +77,7 @@ javaosc-core = { group = "com.illposed.osc", name = "javaosc-core", version.ref
|
|||||||
gson = { group = "com.google.code.gson", name = "gson", version.ref = "gson" }
|
gson = { group = "com.google.code.gson", name = "gson", version.ref = "gson" }
|
||||||
antlr-core = { group = "org.antlr", name = "antlr4", version.ref = "antlr" }
|
antlr-core = { group = "org.antlr", name = "antlr4", version.ref = "antlr" }
|
||||||
antlr-runtime = { group = "org.antlr", name = "antlr4-runtime", version.ref = "antlr" }
|
antlr-runtime = { group = "org.antlr", name = "antlr4-runtime", version.ref = "antlr" }
|
||||||
|
antlr-kotlin-runtime = { group = "com.strumenta", name = "antlr-kotlin-runtime", version.ref = "antlrKotlin" }
|
||||||
|
|
||||||
jupiter-api = { group = "org.junit.jupiter", name = "junit-jupiter-api", version.ref = "junitJupiter" }
|
jupiter-api = { group = "org.junit.jupiter", name = "junit-jupiter-api", version.ref = "junitJupiter" }
|
||||||
jupiter-engine = { group = "org.junit.jupiter", name = "junit-jupiter-engine", version.ref = "junitJupiter" }
|
jupiter-engine = { group = "org.junit.jupiter", name = "junit-jupiter-engine", version.ref = "junitJupiter" }
|
||||||
@@ -86,8 +88,8 @@ slf4j-simple = { group = "org.slf4j", name = "slf4j-simple", version.ref = "slf4
|
|||||||
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
|
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
|
||||||
nebula-release = { id = "nebula.release", version.ref = "nebulaRelease" }
|
nebula-release = { id = "nebula.release", version.ref = "nebulaRelease" }
|
||||||
gradle-nexus-publish = { id = "io.github.gradle-nexus.publish-plugin", version.ref = "gradleNexusPublish" }
|
gradle-nexus-publish = { id = "io.github.gradle-nexus.publish-plugin", version.ref = "gradleNexusPublish" }
|
||||||
kotest-multiplatform = { id = "io.kotest.multiplatform", version.ref = "kotest"}
|
kotest-multiplatform = { id = "io.kotest.multiplatform", version.ref = "kotest" }
|
||||||
|
antlr-kotlin = { id = "com.strumenta.antlr-kotlin", version.ref = "antlrKotlin" }
|
||||||
|
|
||||||
[bundles]
|
[bundles]
|
||||||
jupiter = ["jupiter-api", "jupiter-engine"]
|
jupiter = ["jupiter-api", "jupiter-engine"]
|
||||||
|
|||||||
66
orx-expression-evaluator/build.gradle.kts
Normal file
66
orx-expression-evaluator/build.gradle.kts
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import com.strumenta.antlrkotlin.gradle.AntlrKotlinTask
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
org.openrndr.extra.convention.`kotlin-multiplatform`
|
||||||
|
alias(libs.plugins.antlr.kotlin)
|
||||||
|
}
|
||||||
|
|
||||||
|
val generateKotlinGrammarSource = tasks.register<AntlrKotlinTask>("generateKotlinGrammarSource") {
|
||||||
|
dependsOn("cleanGenerateKotlinGrammarSource")
|
||||||
|
|
||||||
|
// ANTLR .g4 files are under {example-project}/antlr
|
||||||
|
// Only include *.g4 files. This allows tools (e.g., IDE plugins)
|
||||||
|
// to generate temporary files inside the base path
|
||||||
|
source = fileTree(layout.projectDirectory.dir("src/commonMain/antlr")) {
|
||||||
|
include("**/*.g4")
|
||||||
|
}
|
||||||
|
|
||||||
|
// We want the generated source files to have this package name
|
||||||
|
val pkgName = "org.openrndr.expressions.parser"
|
||||||
|
packageName = pkgName
|
||||||
|
|
||||||
|
// We want visitors alongside listeners.
|
||||||
|
// The Kotlin target language is implicit, as is the file encoding (UTF-8)
|
||||||
|
arguments = listOf("-visitor")
|
||||||
|
|
||||||
|
// Generated files are outputted inside build/generatedAntlr/{package-name}
|
||||||
|
val outDir = "generatedAntlr/${pkgName.replace(".", "/")}"
|
||||||
|
outputDirectory = layout.buildDirectory.dir(outDir).get().asFile
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType<KotlinCompile> {
|
||||||
|
kotlinOptions.freeCompilerArgs = listOf("-opt-in=kotlin.RequiresOptIn")
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
sourceSets {
|
||||||
|
val commonMain by getting {
|
||||||
|
dependencies {
|
||||||
|
implementation(libs.antlr.kotlin.runtime)
|
||||||
|
implementation(libs.openrndr.application)
|
||||||
|
implementation(libs.openrndr.math)
|
||||||
|
implementation(libs.kotlin.coroutines)
|
||||||
|
implementation(project(":orx-property-watchers"))
|
||||||
|
implementation(project(":orx-noise"))
|
||||||
|
}
|
||||||
|
kotlin {
|
||||||
|
srcDir(layout.buildDirectory.dir("generatedAntlr"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val jvmDemo by getting {
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":orx-jvm:orx-gui"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val jvmTest by getting {
|
||||||
|
dependencies {
|
||||||
|
implementation(libs.kluent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType<KotlinCompile> {
|
||||||
|
dependsOn(generateKotlinGrammarSource)
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.openrndr.extra.expressions
|
package org.openrndr.extra.expressions
|
||||||
|
|
||||||
import org.antlr.v4.runtime.tree.ParseTreeWalker
|
import org.antlr.v4.kotlinruntime.tree.ParseTreeWalker
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compile a (Double)->Double function from an expression string
|
* Compile a (Double)->Double function from an expression string
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
package org.openrndr.extra.expressions
|
package org.openrndr.extra.expressions
|
||||||
|
|
||||||
import KeyLangLexer
|
|
||||||
import KeyLangParser
|
|
||||||
import KeyLangParserBaseListener
|
import org.antlr.v4.kotlinruntime.*
|
||||||
import org.antlr.v4.runtime.*
|
import org.antlr.v4.kotlinruntime.tree.ParseTreeWalker
|
||||||
import org.antlr.v4.runtime.tree.ParseTreeWalker
|
import org.antlr.v4.kotlinruntime.tree.TerminalNode
|
||||||
import org.antlr.v4.runtime.tree.TerminalNode
|
import org.openrndr.expressions.parser.KeyLangLexer
|
||||||
|
import org.openrndr.expressions.parser.KeyLangParser
|
||||||
|
import org.openrndr.expressions.parser.KeyLangParserBaseListener
|
||||||
|
|
||||||
import org.openrndr.extra.noise.uniform
|
import org.openrndr.extra.noise.uniform
|
||||||
import org.openrndr.math.*
|
import org.openrndr.math.*
|
||||||
@@ -84,11 +86,11 @@ internal class ExpressionListener(
|
|||||||
val right = doubleStack.pop()
|
val right = doubleStack.pop()
|
||||||
val left = doubleStack.pop()
|
val left = doubleStack.pop()
|
||||||
val result = when (val operator = ctx.operator?.type) {
|
val result = when (val operator = ctx.operator?.type) {
|
||||||
KeyLangParser.PLUS -> left + right
|
KeyLangLexer.Tokens.PLUS.id -> left + right
|
||||||
KeyLangParser.MINUS -> left - right
|
KeyLangParser.Tokens.MINUS.id -> left - right
|
||||||
KeyLangParser.ASTERISK -> left * right
|
KeyLangParser.Tokens.ASTERISK.id -> left * right
|
||||||
KeyLangParser.DIVISION -> left / right
|
KeyLangParser.Tokens.DIVISION.id -> left / right
|
||||||
KeyLangParser.PERCENTAGE -> mod(left, right)
|
KeyLangParser.Tokens.PERCENTAGE.id -> mod(left, right)
|
||||||
else -> error("operator '$operator' not implemented")
|
else -> error("operator '$operator' not implemented")
|
||||||
}
|
}
|
||||||
doubleStack.push(result)
|
doubleStack.push(result)
|
||||||
@@ -103,10 +105,10 @@ internal class ExpressionListener(
|
|||||||
val left = doubleStack.pop()
|
val left = doubleStack.pop()
|
||||||
val right = doubleStack.pop()
|
val right = doubleStack.pop()
|
||||||
val result = when (val operator = ctx.operator?.type) {
|
val result = when (val operator = ctx.operator?.type) {
|
||||||
KeyLangParser.PLUS -> left + right
|
KeyLangParser.Tokens.PLUS.id -> left + right
|
||||||
KeyLangParser.MINUS -> right - left
|
KeyLangParser.Tokens.MINUS.id -> right - left
|
||||||
KeyLangParser.ASTERISK -> left * right
|
KeyLangParser.Tokens.ASTERISK.id -> left * right
|
||||||
KeyLangParser.DIVISION -> left / right
|
KeyLangParser.Tokens.DIVISION.id -> left / right
|
||||||
else -> error("operator '$operator' not implemented")
|
else -> error("operator '$operator' not implemented")
|
||||||
}
|
}
|
||||||
doubleStack.push(result)
|
doubleStack.push(result)
|
||||||
@@ -245,13 +247,13 @@ internal class ExpressionListener(
|
|||||||
|
|
||||||
override fun visitTerminal(node: TerminalNode) {
|
override fun visitTerminal(node: TerminalNode) {
|
||||||
val type = node.symbol?.type
|
val type = node.symbol?.type
|
||||||
if (type == KeyLangParser.INTLIT) {
|
if (type == KeyLangParser.Tokens.INTLIT.id) {
|
||||||
doubleStack.push(node.text.toDouble())
|
doubleStack.push(node.text.toDouble())
|
||||||
}
|
}
|
||||||
if (type == KeyLangParser.DECLIT) {
|
if (type == KeyLangParser.Tokens.DECLIT.id) {
|
||||||
doubleStack.push(node.text.toDouble())
|
doubleStack.push(node.text.toDouble())
|
||||||
}
|
}
|
||||||
if (type == KeyLangParser.ID) {
|
if (type == KeyLangParser.Tokens.ID.id) {
|
||||||
val name = node.text.replace("`", "")
|
val name = node.text.replace("`", "")
|
||||||
@Suppress("DIVISION_BY_ZERO")
|
@Suppress("DIVISION_BY_ZERO")
|
||||||
when (val idType = idTypeStack.pop()) {
|
when (val idType = idTypeStack.pop()) {
|
||||||
@@ -409,11 +411,11 @@ fun evaluateExpression(
|
|||||||
parser.removeErrorListeners()
|
parser.removeErrorListeners()
|
||||||
parser.addErrorListener(object : BaseErrorListener() {
|
parser.addErrorListener(object : BaseErrorListener() {
|
||||||
override fun syntaxError(
|
override fun syntaxError(
|
||||||
recognizer: Recognizer<*, *>?,
|
recognizer: Recognizer<*, *>,
|
||||||
offendingSymbol: Any?,
|
offendingSymbol: Any?,
|
||||||
line: Int,
|
line: Int,
|
||||||
charPositionInLine: Int,
|
charPositionInLine: Int,
|
||||||
msg: String?,
|
msg: String,
|
||||||
e: RecognitionException?
|
e: RecognitionException?
|
||||||
) {
|
) {
|
||||||
throw ExpressionException("parser error in expression: '$expression'; [line: $line, character: $charPositionInLine ${offendingSymbol?.let { ", near: $it" } ?: ""} ]")
|
throw ExpressionException("parser error in expression: '$expression'; [line: $line, character: $charPositionInLine ${offendingSymbol?.let { ", near: $it" } ?: ""} ]")
|
||||||
@@ -440,11 +442,11 @@ fun compileExpression(
|
|||||||
parser.removeErrorListeners()
|
parser.removeErrorListeners()
|
||||||
parser.addErrorListener(object : BaseErrorListener() {
|
parser.addErrorListener(object : BaseErrorListener() {
|
||||||
override fun syntaxError(
|
override fun syntaxError(
|
||||||
recognizer: Recognizer<*, *>?,
|
recognizer: Recognizer<*, *>,
|
||||||
offendingSymbol: Any?,
|
offendingSymbol: Any?,
|
||||||
line: Int,
|
line: Int,
|
||||||
charPositionInLine: Int,
|
charPositionInLine: Int,
|
||||||
msg: String?,
|
msg: String,
|
||||||
e: RecognitionException?
|
e: RecognitionException?
|
||||||
) {
|
) {
|
||||||
throw ExpressionException("parser error in expression: '$expression'; [line: $line, character: $charPositionInLine ${offendingSymbol?.let { ", near: $it" } ?: ""} ]")
|
throw ExpressionException("parser error in expression: '$expression'; [line: $line, character: $charPositionInLine ${offendingSymbol?.let { ", near: $it" } ?: ""} ]")
|
||||||
@@ -470,11 +472,11 @@ internal fun expressionRoot(expression: String): KeyLangParser.KeyLangFileContex
|
|||||||
parser.removeErrorListeners()
|
parser.removeErrorListeners()
|
||||||
parser.addErrorListener(object : BaseErrorListener() {
|
parser.addErrorListener(object : BaseErrorListener() {
|
||||||
override fun syntaxError(
|
override fun syntaxError(
|
||||||
recognizer: Recognizer<*, *>?,
|
recognizer: Recognizer<*, *>,
|
||||||
offendingSymbol: Any?,
|
offendingSymbol: Any?,
|
||||||
line: Int,
|
line: Int,
|
||||||
charPositionInLine: Int,
|
charPositionInLine: Int,
|
||||||
msg: String?,
|
msg: String,
|
||||||
e: RecognitionException?
|
e: RecognitionException?
|
||||||
) {
|
) {
|
||||||
throw ExpressionException("parser error in expression: '$expression'; [line: $line, character: $charPositionInLine ${offendingSymbol?.let { ", near: $it" } ?: ""} ]")
|
throw ExpressionException("parser error in expression: '$expression'; [line: $line, character: $charPositionInLine ${offendingSymbol?.let { ", near: $it" } ?: ""} ]")
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
|
||||||
|
|
||||||
plugins {
|
|
||||||
org.openrndr.extra.convention.`kotlin-jvm`
|
|
||||||
antlr
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.generateGrammarSource {
|
|
||||||
maxHeapSize = "64m"
|
|
||||||
arguments.addAll(listOf("-visitor", "-long-messages"))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
tasks.withType<KotlinCompile> {
|
|
||||||
kotlinOptions.freeCompilerArgs = listOf("-opt-in=kotlin.RequiresOptIn")
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
antlr(libs.antlr.core)
|
|
||||||
implementation(libs.antlr.runtime)
|
|
||||||
implementation(libs.openrndr.application)
|
|
||||||
implementation(libs.openrndr.math)
|
|
||||||
implementation(libs.kotlin.coroutines)
|
|
||||||
implementation(project(":orx-property-watchers"))
|
|
||||||
implementation(project(":orx-noise"))
|
|
||||||
testImplementation(libs.kluent)
|
|
||||||
demoImplementation(project(":orx-jvm:orx-gui"))
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.getByName("compileKotlin").dependsOn("generateGrammarSource")
|
|
||||||
tasks.getByName("compileDemoKotlin").dependsOn("generateDemoGrammarSource")
|
|
||||||
tasks.getByName("compileTestKotlin").dependsOn("generateTestGrammarSource")
|
|
||||||
tasks.getByName("sourcesJar").dependsOn("generateGrammarSource")
|
|
||||||
@@ -15,7 +15,7 @@ dependencies {
|
|||||||
implementation(libs.kotlin.reflect)
|
implementation(libs.kotlin.reflect)
|
||||||
implementation(project(":orx-noise"))
|
implementation(project(":orx-noise"))
|
||||||
implementation(project(":orx-easing"))
|
implementation(project(":orx-easing"))
|
||||||
api(project(":orx-jvm:orx-expression-evaluator"))
|
api(project(":orx-expression-evaluator"))
|
||||||
demoImplementation(project(":orx-jvm:orx-panel"))
|
demoImplementation(project(":orx-jvm:orx-panel"))
|
||||||
testImplementation(libs.kluent)
|
testImplementation(libs.kluent)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ tasks.test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(":orx-jvm:orx-expression-evaluator"))
|
implementation(project(":orx-expression-evaluator"))
|
||||||
implementation(libs.openrndr.application)
|
implementation(libs.openrndr.application)
|
||||||
implementation(libs.openrndr.math)
|
implementation(libs.openrndr.math)
|
||||||
implementation(libs.kotlin.coroutines)
|
implementation(libs.kotlin.coroutines)
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ include(
|
|||||||
"orx-jvm:orx-dnk3",
|
"orx-jvm:orx-dnk3",
|
||||||
"orx-easing",
|
"orx-easing",
|
||||||
"orx-envelopes",
|
"orx-envelopes",
|
||||||
"orx-jvm:orx-expression-evaluator",
|
"orx-expression-evaluator",
|
||||||
"orx-jvm:orx-file-watcher",
|
"orx-jvm:orx-file-watcher",
|
||||||
"orx-parameters",
|
"orx-parameters",
|
||||||
"orx-fx",
|
"orx-fx",
|
||||||
|
|||||||
Reference in New Issue
Block a user