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

commonMain.piacenti.dslmaker.structures.Grammar.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.structures

import piacenti.dslmaker.abstraction.ProductionStep
import piacenti.dslmaker.interfaces.GrammarInventory
import piacenti.dslmaker.interfaces.MatchData


/**
 * @param 
 * @author Piacenti
 */
open class Grammar(var startProduction: ProductionStep, val container: T) {
    /**
     * @return
     */
    val productions: MutableMap = mutableMapOf()

    private val tokenContainsMap = HashMap>()

    fun wrapTokensWithProductions() {
        val alreadyProcessed = HashMap()
        val toAdd = HashMap()
        val productionNames = HashSet()
        productions.forEach { t -> productionNames.add(t.key.name) }
        productions.forEach { t ->
            t.value.expressions.forEach { tExpression ->
                for (i in 0 until tExpression.steps.size) {
                    val step = tExpression.steps[i]
                    if (alreadyProcessed[step] == null) {
                        if (thereIsNoMatchingProductionForThisStep(step, productionNames)) {
                            try {
                                val newProductionStep = ProductionStep(
                                        step.name.toUpperCase().replace("_LEAF".toRegex(), ""))
                                val newProduction = Production(null)
                                newProduction.expressions.add(Expression(step))
                                toAdd[newProductionStep] = newProduction
                                alreadyProcessed[step] = newProductionStep
                                tExpression.steps[i] = newProductionStep

                            } catch (e: Throwable) {
                                println(e.message)
                            }

                        }
                    } else {
                        //replace step in parent with production
                        tExpression.steps[i] = alreadyProcessed[step]!!
                    }
                }
            }
        }
        productions.putAll(toAdd)
    }

    private fun thereIsNoMatchingProductionForThisStep(step: ProductionStep, productionNames: Set): Boolean {
        if (step.isProduction) return false
        //productions by convention should be upper case
        var name = step.name.toUpperCase()
        //tokens following the _LEAF ending convention should be disconsidered
        if (name.endsWith("_LEAF")) {
            name = name.replace("_LEAF", "")
        }
        return !productionNames.contains(name)
    }

    fun clearAllActions(): Grammar {
        productions.entries.forEach { tProductionEntry -> tProductionEntry.value.action = null }
        return this
    }

    fun getAllTokensContainingProduction(production: ProductionStep): Set {
        val value = tokenContainsMap[production]
        if (value != null) {
            return value
        }
        val result = HashSet()
        productions.entries.forEach { prod ->
            prod.value.expressions.forEach { exp ->
                exp.steps.forEach { step ->
                    if (step === production) {
                        result.add(prod.key)
                    }
                }
            }
        }
        tokenContainsMap[production] = result
        return result
    }

    override fun toString(): String {
        val result = StringBuilder()
        result.append(startProduction).append(" -> ").append(productions[startProduction]).append("\n")
        productions.entries.filter { entry -> entry.key !== startProduction }.sortedBy { it.toString() }.forEach { entry ->
            result.append(entry.key).append(" -> ")
            result.append(entry.value).append("\n")
        }
        return result.toString()
    }

    fun p(value: ProductionStep, vararg exps: Expression) {
        if (productions[value] == null) {
            productions[value] = Production(null)
        }
        productions[value]!!.expressions.clear()
        productions[value]!!.expressions.addAll(exps)
    }

    fun r(value: ProductionStep, vararg exps: Expression) {
        p(value, *exps)
    }

    fun pAppend(value: ProductionStep, vararg exps: Expression) {
        if (productions[value] == null) {
            productions[value] = Production(null)
        }
        productions[value]!!.expressions.addAll(exps)
    }

    fun a(value: ProductionStep, action: ((MatchData) -> Unit)?) {
        if (value.isProduction) {
            if (productions[value] == null) {
                productions[value] = Production(null)
            }
            productions[value]!!.action = action
        }
    }


    fun e(vararg exps: ProductionStep): Expression {
        return Expression(*exps)
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy