All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.piacenti.dslmaker.dsl.Completion.kt Maven / Gradle / Ivy

Go to download

Kotlin multiplatform library to facilitate creation of DSLs with ANTLR or a simple built in parser

There is a newer version: 1.1.55
Show newest version
package piacenti.dslmaker.dsl

import kotlinx.serialization.Serializable
import piacenti.dslmaker.GenericParser2
import piacenti.dslmaker.abstraction.ProductionStep
import piacenti.dslmaker.errors.ParserException
import piacenti.dslmaker.structures.ASTNode
import piacenti.dslmaker.structures.Grammar

@Serializable
data class Range(val value: T?, val start: Int, val end: Int)

@Serializable
data class Completion(val completionText: String, val text: String, val startOfReplace: Int, val caretPosition: Int, val type: String? = null, val completionCustomAction: ((Range, Completion) -> Unit)? = null)

interface AutoCompleter {
    fun suggestCompletion(text: String,
                          startOfCompletionCaretPosition: Int,
                          currentCaretPosition: Int = startOfCompletionCaretPosition,
                          astBasedAction: ((result: MutableSet, ast: ASTNode) -> Unit)? = null): List
}

abstract class GrammarBasedAutoCompleter(val grammar: Grammar<*>) : AutoCompleter {
    private val parser = GenericParser2(grammar)
    abstract fun stepToCompletions(step:ProductionStep, completionFactory:(text:String,type:String)->Completion):List
    private fun generateCompletions(text: String, startOfCompletionCaretPosition: Int, currentCaretPosition: Int, steps: Set): List {

        val result = mutableListOf()
        val curry: (String, String) -> Completion = { completionText, completionType ->
            Completion(completionText, text, startOfCompletionCaretPosition, currentCaretPosition, completionType)
        }
        steps.forEach { step ->
            result.addAll(stepToCompletions(step, curry))
        }
        return result
    }
    override fun suggestCompletion(text: String,
                                   startOfCompletionCaretPosition: Int,
                                   currentCaretPosition: Int,
                                   astBasedAction: ((result: MutableSet, ast: ASTNode) -> Unit)?): List {
        val result = mutableSetOf()
        try {
            val evalText = text.substring(0, startOfCompletionCaretPosition)
            val ast = parser.parse(evalText, true)
            if (astBasedAction != null) {
                ast.forEachRecursive({
                    astBasedAction(result, it)
                })
            }
        } catch (ex: ParserException) {
            //while writing we do not want to see lots of parse errors
        }
        if (result.isEmpty())
            result.addAll(generateCompletions(text, startOfCompletionCaretPosition, currentCaretPosition, parser.expectedTokenNotMatched))
        if (result.isEmpty())
            result.addAll(generateCompletions(text, startOfCompletionCaretPosition, currentCaretPosition, parser.possibleValidTokensIfContinuingParsing))
        return CompletionRanker().rank(result)
    }

}

class CompletionRanker {
    fun rank(completions: Set): List {
        return completions.sortedWith(compareBy {
            val substring = it.text.substring(it.startOfReplace, it.caretPosition)
            when {
                substring.isNotBlank() -> substring.similarity(it.completionText)
                else -> 1
            }
        }).reversed()
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy