Strumenta / antlr-kotlin

Support for Kotlin as a target for ANTLR 4
Apache License 2.0
222 stars 47 forks source link

Generated parser contains invalid Kotlin code #106

Closed borsini closed 9 months ago

borsini commented 10 months ago

Hello and first of all thank you for your work!

I discovered antlr recently and was playing with antlr-kotlin in order to generate a parser and a lexer for this grammar.

ℹ️ A sample repo can be found here

The lexer is generated perfectly, but the parser code contains some errors 👇
They are easy to fix, but it becomes tedious as each time I make a change on the grammar I need to patch the parser again.

I would have liked to contribute by opening a pull request to fix the issue. But I'm a newbie on this subject (antlr/grammars) and woldn't know where to start without a little bit of help.

> Task :compileKotlinJvm FAILED
e: file:///Users/.../TxnParser.kt:705:3 Property must be initialized or be abstract
e: file:///Users/.../TxnParser.kt:705:11 Unresolved reference: int
e: file:///Users/.../TxnParser.kt:706:3 Property must be initialized or be abstract
e: file:///Users/.../TxnParser.kt:706:11 Unresolved reference: int
e: file:///Users/.../TxnParser.kt:707:3 Property must be initialized or be abstract
e: file:///Users/.../TxnParser.kt:707:11 Unresolved reference: int
e: file:///Users/.../TxnParser.kt:717:63 'var' on secondary constructor parameter is not allowed
e: file:///Users/.../TxnParser.kt:717:71 Unresolved reference: int
e: file:///Users/.../TxnParser.kt:717:76 'var' on secondary constructor parameter is not allowed
e: file:///Users/.../TxnParser.kt:717:84 Unresolved reference: int
e: file:///Users/.../TxnParser.kt:717:89 'var' on secondary constructor parameter is not allowed
e: file:///Users/.../TxnParser.kt:717:97 Unresolved reference: int
e: file:///Users/.../TxnParser.kt:730:16 'var' on function parameter is not allowed
e: file:///Users/.../TxnParser.kt:730:24 Unresolved reference: int
e: file:///Users/.../TxnParser.kt:730:28 'var' on function parameter is not allowed
e: file:///Users/.../TxnParser.kt:730:36 Unresolved reference: int
e: file:///Users/.../TxnParser.kt:730:40 'var' on function parameter is not allowed
e: file:///Users/.../TxnParser.kt:730:48 Unresolved reference: int

Screenshot 2023-11-03 at 14 55 15 Screenshot 2023-11-03 at 14 55 33

borsini commented 10 months ago

By the time a solution is found, I came with a workaround: fixing errors using regular expressions replacement directly in generated Kotlin files.

Something like

tasks.register("fixGeneratedParserKotlinCode") {

    outputs.upToDateWhen { false }
    val directory = File(projectDir, generatedSourcesDirectory)

    val funRegex = "var (\\w) : int([\\,,\\)])".toRegex() to "$1: Int$2"
    val valRegex = "(.*)var (.*) : int".toRegex() to "$1var $2 = 0"

    val regexps = listOf(funRegex, valRegex)

    if (!directory.isDirectory) {
        println("Invalid directory $directory.")
        return@register
    }

    doLast {
        val generatedKotlinFiles = fileTree(directory).matching { include("*.kt") }.files

        generatedKotlinFiles.forEach { inputFile ->
            val tempFile = File(temporaryDir, "${inputFile.name}.tmp")

            inputFile.bufferedReader().use { reader ->
                tempFile.bufferedWriter().use { writer ->
                    reader.forEachLine { line ->

                        val modifiedLine = regexps.fold(line) { acc: String, (regex, replacement) ->
                            regex.replace(input = acc, replacement = replacement)
                        }

                        writer.write(modifiedLine)
                        writer.newLine()
                    }
                }
            }

            if (inputFile.delete() && tempFile.renameTo(inputFile)) {
                println("File ${inputFile.name} modified successfully.")
            } else {
                println("Error modifying the file.")
            }
        }
    }

    dependsOn("generateKotlinCommonGrammarSource")
}