import java.util.* fun defineAst(baseName: String, types: List) { println("package fr.celticinfo.lox") println() println("interface ${baseName}Visitor {") for (type in types) { val parts = type.split(":") val name = parts[0].trim() println(" fun visit$name(${baseName.lowercase(Locale.getDefault())}: $name): R") } println("}") println() println("sealed class $baseName {") println(" abstract fun accept(visitor: ${baseName}Visitor): R") println("}") for (type in types) { val parts = type.split(":") val name = parts[0].trim() val fields = parts[1].trim().split(",").map { it.trim() } println() println("data class $name(") for (field in fields) { val fparts = field.split(" ") val ftype = fparts[0] val fname = fparts[1] val sep = if (field == fields.last()) "" else "," println(" val $fname: $ftype$sep") } println(") : ${baseName}() {") println(" override fun accept(visitor: ${baseName}Visitor): R {") println(" return visitor.visit$name(this)") println(" }") println("}") } } val exprTypes = listOf( "Assign : Token name, Expr value", "Binary : Expr left, Token operator, Expr right", "Call : Expr callee, Token paren, List arguments", "Grouping : Expr expression", "Literal : Any? value", "Logical : Expr left, Token operator, Expr right", "Unary : Token operator, Expr right", "Variable : Token name" ) defineAst("Expr", exprTypes) val stmtTypes = listOf( "Block : List statements", "Expression : Expr expression", "If : Expr condition, Stmt thenBranch, Stmt? elseBranch", "Print : Expr expression", "Var : Token name, Expr? initializer", "While : Expr condition, Stmt body" ) defineAst("Stmt", stmtTypes)