Skip to content

Commit

Permalink
fix: replace antlr with regex to solve did creation issues (#114)
Browse files Browse the repository at this point in the history
  • Loading branch information
cristianIOHK authored Nov 27, 2023
1 parent cecbbb1 commit 854fc70
Show file tree
Hide file tree
Showing 14 changed files with 70 additions and 305 deletions.
37 changes: 4 additions & 33 deletions atala-prism-sdk/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ koverReport {
packages(
"io.iohk.atala.prism.protos",
"io.iohk.atala.prism.walletsdk.domain",
"io.iohk.atala.prism.walletsdk.castor.antlrgrammar",
"ioiohkatalaprismwalletsdkpluto.data"
)
}
Expand All @@ -56,15 +55,7 @@ kotlin {
}

sourceSets {
val commonAntlr by creating {
kotlin.srcDir("build/generated-src/commonAntlr/kotlin")
dependencies {
api(kotlin("stdlib-common"))
api("com.github.piacenti:antlr-kotlin-runtime:0.0.14")
}
}
val commonMain by getting {
this.dependsOn(commonAntlr)
kotlin.srcDir("${project(":protosLib").buildDir}/generated/source/proto/main/kotlin")
resources.srcDir("${project(":protosLib").projectDir}/src/main")
dependencies {
Expand Down Expand Up @@ -232,26 +223,6 @@ tasks.withType<DokkaTask>().configureEach {
}
}

val antlrGenerationTask by tasks.register<com.strumenta.antlrkotlin.gradleplugin.AntlrKotlinTask>("generateKotlinCommonGrammarSource") {
// the classpath used to run antlr code generation
antlrClasspath = configurations.detachedConfiguration(
project.dependencies.create("com.github.piacenti:antlr-kotlin-runtime:0.0.14")
)
maxHeapSize = "64m"
packageName = "io.iohk.atala.prism.walletsdk.castor.antlrgrammar"
arguments = listOf("-long-messages", "-Dlanguage=JavaScript")
source = project.objects
.sourceDirectorySet("antlr", "antlr")
.srcDir("src/commonAntlr/antlr").apply {
include("*.g4")
}
// outputDirectory is required, put it into the build directory
// if you do not want to add the generated sources to version control
outputDirectory = File("build/generated-src/commonAntlr/kotlin")
// use this setting if you want to add the generated sources to version control
// outputDirectory = File("src/commonAntlr/kotlin")
}

val buildProtoLibsGen by tasks.creating {
group = "build"
this.dependsOn(":protosLib:generateProto")
Expand All @@ -265,17 +236,17 @@ afterEvaluate {
this.enabled = false
}
tasks.getByName("runKtlintCheckOverCommonMainSourceSet") {
dependsOn(buildProtoLibsGen, antlrGenerationTask)
dependsOn(buildProtoLibsGen)
}
tasks.getByName("build") {
dependsOn(buildProtoLibsGen, antlrGenerationTask)
dependsOn(buildProtoLibsGen)
}

tasks.withType<KotlinCompile> {
dependsOn(buildProtoLibsGen, antlrGenerationTask)
dependsOn(buildProtoLibsGen)
}

tasks.withType<ProcessResources> {
dependsOn(buildProtoLibsGen, antlrGenerationTask)
dependsOn(buildProtoLibsGen)
}
}
34 changes: 0 additions & 34 deletions atala-prism-sdk/src/commonAntlr/antlr/DIDAbnf.g4

This file was deleted.

62 changes: 0 additions & 62 deletions atala-prism-sdk/src/commonAntlr/antlr/DIDUrlAbnf.g4

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,34 +1,23 @@
package io.iohk.atala.prism.walletsdk.castor.did

import io.iohk.atala.prism.walletsdk.castor.antlrgrammar.DIDAbnfLexer
import io.iohk.atala.prism.walletsdk.castor.antlrgrammar.DIDAbnfParser
import io.iohk.atala.prism.walletsdk.domain.models.CastorError
import io.iohk.atala.prism.walletsdk.domain.models.DID
import org.antlr.v4.kotlinruntime.CharStreams
import org.antlr.v4.kotlinruntime.CommonTokenStream
import org.antlr.v4.kotlinruntime.tree.ParseTree
import org.antlr.v4.kotlinruntime.tree.ParseTreeWalker
import kotlin.jvm.Throws

object DIDParser {

@Throws(CastorError.InvalidDIDString::class)
fun parse(didString: String): DID {
val inputStream = CharStreams.fromString(didString)
val lexer = DIDAbnfLexer(inputStream)
val tokenStream = CommonTokenStream(lexer)
val parser = DIDAbnfParser(tokenStream)

parser.errorHandler = ErrorStrategy()

val context = parser.did()
val listener = DIDParserListener()
ParseTreeWalker().walk(listener, context as ParseTree)

val scheme = listener.scheme ?: throw CastorError.InvalidDIDString("Invalid DID string, missing scheme")
val methodName = listener.methodName ?: throw CastorError.InvalidDIDString("Invalid DID string, missing method name")
val methodId = listener.methodId ?: throw CastorError.InvalidDIDString("Invalid DID string, missing method ID")

return DID(scheme, methodName, methodId)
val regex =
"""^did:(?<method>[a-z0-9]+):(?<idstring>[a-z0-9.\-_%]+:*[a-z0-9.\-_%]+[^#?:]+)$""".toRegex(RegexOption.IGNORE_CASE)
val matchResult = regex.find(didString)
matchResult?.let {
val scheme = "did"
val methodName = it.groups["method"]?.value
?: throw CastorError.InvalidDIDString("Invalid DID string, missing method name")
val methodId = it.groups["idstring"]?.value
?: throw CastorError.InvalidDIDString("Invalid DID string, missing method ID")
return DID(scheme, methodName, methodId)
} ?: throw CastorError.InvalidDIDString("DID string does not match the expected structure.")
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,41 +1,40 @@
package io.iohk.atala.prism.walletsdk.castor.did

import io.iohk.atala.prism.walletsdk.castor.antlrgrammar.DIDUrlAbnfLexer
import io.iohk.atala.prism.walletsdk.castor.antlrgrammar.DIDUrlAbnfParser
import io.iohk.atala.prism.walletsdk.domain.models.CastorError
import io.iohk.atala.prism.walletsdk.domain.models.DID
import io.iohk.atala.prism.walletsdk.domain.models.DIDUrl
import org.antlr.v4.kotlinruntime.CharStreams
import org.antlr.v4.kotlinruntime.CommonTokenStream
import org.antlr.v4.kotlinruntime.tree.ParseTree
import org.antlr.v4.kotlinruntime.tree.ParseTreeWalker
import kotlin.jvm.Throws

object DIDUrlParser {
@Throws(CastorError.InvalidDIDString::class)
fun parse(didUrlString: String): DIDUrl {
val inputStream = CharStreams.fromString(didUrlString)
val lexer = DIDUrlAbnfLexer(inputStream)
val tokenStream = CommonTokenStream(lexer)
val parser = DIDUrlAbnfParser(tokenStream)
val regex =
"""^did:(?<method>[a-z0-9]+)(?::(?<idstring>[^#?/]*))?(?<path>[^#?]*)?(?<query>\?[^#]*)?(?<fragment>#.*)?$""".toRegex(
RegexOption.IGNORE_CASE
)
val matchResult = regex.find(didUrlString)

parser.errorHandler = ErrorStrategy()

val context = parser.did_url()
val listener = DIDUrlParserListener()
ParseTreeWalker().walk(listener, context as ParseTree)

val scheme = listener.scheme ?: throw CastorError.InvalidDIDString("Invalid DID string, missing scheme")
val methodName = listener.methodName ?: throw CastorError.InvalidDIDString("Invalid DID string, missing method name")
val methodId = listener.methodId ?: throw CastorError.InvalidDIDString("Invalid DID string, missing method ID")

val did = DID(scheme, methodName, methodId)

return DIDUrl(
did,
listener.path ?: emptyArray(),
listener.query,
listener.fragment
)
matchResult?.let { it ->
val method = it.groups["method"]?.value
?: throw CastorError.InvalidDIDString("Invalid DID string, missing method name")
val idString = it.groups["idstring"]?.value
?: throw CastorError.InvalidDIDString("Invalid DID string, missing method ID")
val path =
it.groups["path"]?.value ?: throw CastorError.InvalidDIDString("Invalid DID string, missing path")
val query = it.groups["query"]?.value ?: ""
val fragment = it.groups["fragment"]?.value ?: ""
val attributes = if (query.isNotEmpty()) {
query.removePrefix("?").split("&")
.associate {
val (key, value) = it.split("=")
key to (value ?: "")
}
} else {
mapOf()
}
val paths = path.split("/").filter { it.isNotEmpty() }.toTypedArray()
val did = DID("did", method, idString)
val fragmentValue = if (fragment.isNotEmpty()) fragment.removePrefix("#") else null
return DIDUrl(did, paths, attributes, fragmentValue)
} ?: throw CastorError.InvalidDIDString("DID string does not match the expected structure.")
}
}

This file was deleted.

This file was deleted.

Loading

0 comments on commit 854fc70

Please sign in to comment.