commonMain.piacenti.dslmaker.structures.Grammar.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dsl-maker-js Show documentation
Show all versions of dsl-maker-js Show documentation
Kotlin multiplatform library to facilitate creation of DSLs with ANTLR or a simple built in parser
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