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

org.jglrxavpok.hephaistos.SNBTParsingVisitor.kt Maven / Gradle / Ivy

There is a newer version: 2.6.1
Show newest version
package org.jglrxavpok.hephaistos

import org.jglrxavpok.hephaistos.antlr.SNBTBaseVisitor
import org.jglrxavpok.hephaistos.antlr.SNBTParser
import org.jglrxavpok.hephaistos.nbt.*
import java.lang.StringBuilder

object SNBTParsingVisitor: SNBTBaseVisitor() {

    override fun aggregateResult(aggregate: NBT?, nextResult: NBT?): NBT? {
        return when {
            aggregate == null && nextResult != null -> nextResult
            aggregate != null && nextResult == null -> aggregate
            aggregate == null && nextResult == null -> null
            else -> /*aggregate != null && nextResult != null ->*/ error("Can't merge $aggregate and $nextResult")
        }
    }

    override fun visitCompound(ctx: SNBTParser.CompoundContext): NBT = NBT.Kompound {
        ctx.namedElement().forEach {
            this[(visit(it.name) as NBTString).value] = visit(it.value)
        }
    }


    override fun visitList(ctx: SNBTParser.ListContext): NBT {
        val elements = ctx.element().map { visit(it) }
        val subtagType = if (elements.isEmpty()) NBTType.TAG_String else elements[0].ID
        return NBT.List(subtagType, elements)
    }

    override fun visitByteArray(ctx: SNBTParser.ByteArrayContext): NBT {
        val array = ctx.byteNBT().map { (visitByteNBT(it) as NBTByte).value }.toByteArray()
        return NBT.ByteArray(*array)
    }

    override fun visitIntArray(ctx: SNBTParser.IntArrayContext): NBT {
        val array = ctx.intNBT().map { (visitIntNBT(it) as NBTInt).value }.toIntArray()
        return NBT.IntArray(*array)
    }

    override fun visitLongArray(ctx: SNBTParser.LongArrayContext): NBT {
        val array = ctx.longNBT().map { (visitLongNBT(it) as NBTLong).value }.toLongArray()
        return NBT.LongArray(*array)
    }

    override fun visitDoubleNBT(ctx: SNBTParser.DoubleNBTContext): NBT {
        var text = ctx.text
        if (text.endsWith('d') || text.endsWith('D')) {
            text = text.dropLast(1)
        }
        return NBT.Double(text.toDouble())
    }

    override fun visitFloatNBT(ctx: SNBTParser.FloatNBTContext): NBT {
        return NBT.Float(ctx.text.dropLast(1).toFloat())
    }

    override fun visitLongNBT(ctx: SNBTParser.LongNBTContext): NBT {
        val value = ctx.LONG().text.dropLast(1).toLong()
        return NBT.Long(value)
    }

    override fun visitByteNBT(ctx: SNBTParser.ByteNBTContext): NBT {
        ctx.BOOLEAN()?.let {
            val booleanValue = ctx.BOOLEAN().text == "true"
            return NBT.Boolean(booleanValue)
        }
        val value = ctx.BYTE().text.dropLast(1).toByte()
        return NBT.Byte(value)
    }

    override fun visitShortNBT(ctx: SNBTParser.ShortNBTContext): NBT {
        val value = ctx.SHORT().text.dropLast(1).toShort()
        return NBT.Short(value)
    }

    private fun unescape(str: String): String {
        var escaped = false
        val buffer = StringBuilder()
        for (c in str) {
            if(escaped) {
                when(c) {
                    '\\', '"' -> {
                        buffer.append(c)
                        escaped = false
                    }
                    else -> error("Unrecognized escape sequence: \\$c")
                }
            } else if(c == '\\') {
                escaped = true;
            } else {
                buffer.append(c)
            }
        }
        return buffer.toString()
    }

    override fun visitStringNBT(ctx: SNBTParser.StringNBTContext): NBT {
        return when {
            ctx.DoubleQuoteText() != null -> NBT.String(unescape(ctx.DoubleQuoteText().text.drop(1).dropLast(1)))
            ctx.SingleQuoteText() != null -> NBT.String(unescape(ctx.SingleQuoteText().text.drop(1).dropLast(1)))
            else -> NBT.String(ctx.text)
        }
    }

    override fun visitIntNBT(ctx: SNBTParser.IntNBTContext): NBT {
        return NBT.Int(ctx.INTEGER().text.toInt())
    }

    override fun visitIdentifier(ctx: SNBTParser.IdentifierContext?): NBT? {
        error("Should not access this rule directly")
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy