Last active
January 3, 2016 12:37
-
-
Save Jire/6ecb8315a963ec653b14 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package org.jire.kton | |
| import java.util.* | |
| /** | |
| * Represents an instance of KTON (Kotlin object notation). | |
| * | |
| * @author Thomas Nappo | |
| */ | |
| class KTON(private var arrCursor: Int = -1) { | |
| private var lastCursor = arrCursor | |
| /** | |
| * Maps string keys with their values. | |
| */ | |
| private val vars = HashMap<String, Any>() | |
| /** | |
| * Gets the corresponding value of a key, potentially `null`. | |
| * | |
| * @param key The key of the value. | |
| */ | |
| operator fun get(key: String) = vars[formatKey(key)] | |
| /** | |
| * Gets the corresponding KTON body of a key. | |
| * | |
| * @param key The key of the body. | |
| */ | |
| operator fun invoke(key: String) = this[key]!! as KTON | |
| /** | |
| * Gets the corresponding KTON array of an index. | |
| * | |
| * @param index The index of the array (of declaration order). | |
| */ | |
| operator fun get(index: Int): KTON { | |
| arrCursor = index | |
| return this | |
| } | |
| /** | |
| * Establishes (maps) a value to the current string in a KTON. | |
| */ | |
| infix fun <V : Any> String.to(value: V) { | |
| vars[formatKey(this)] = value | |
| } | |
| /** | |
| * Establishes (maps) a body to the current string in a KTON. | |
| * | |
| * @param body The body representing the new KTON. | |
| */ | |
| operator fun <O> String.invoke(body: KTON.() -> O) = to(kton(body)) | |
| operator fun <O> (() -> O).unaryPlus() { | |
| if (arrCursor >= 0) throw UnsupportedOperationException("Multi-dimension arrays not supported!") | |
| arrCursor = lastCursor + 1 | |
| this() | |
| lastCursor = arrCursor | |
| arrCursor = -1 | |
| } | |
| private fun formatKey(key: String) = if (arrCursor < 0) key else "[$arrCursor][$key]" | |
| } | |
| /** | |
| * Creates a KTON using the supplied body. | |
| * | |
| * @param body The body of the KTON used to declare more KTONs or values. | |
| */ | |
| inline fun <O> kton(body: KTON.() -> O): KTON { | |
| val kton = KTON() | |
| kton.body() | |
| return kton | |
| } | |
| fun main(args: Array<String>) { | |
| val menu = kton { | |
| "id" to "file" | |
| "value" to "File" | |
| "popup" { | |
| "menuitem" { | |
| +{ "value" to "New"; "onclick" to "CreateNewDoc()" } | |
| +{ "value" to "Open"; "onclick" to "OpenDoc()" } | |
| +{ "value" to "Close"; "onclick" to "CloseDoc()" } | |
| } | |
| } | |
| } | |
| // Value access through get operator: | |
| val id = menu["id"] // "file" | |
| val value = menu["value"] // "File" | |
| // Body access through invoke operator: | |
| val popup = menu("popup") | |
| val menuitems = popup("menuitem") | |
| // Array access through get operator specifying index: | |
| val newValue = menuitems[0]["value"] // "New" | |
| val open = menuitems[1] | |
| val openValue = open["value"] // "Open" | |
| val closeOnClick = menuitems[2]["onclick"] // "CloseDoc()" | |
| assert(id == "File") | |
| assert(value == "File") | |
| assert(newValue == "New") | |
| assert(openValue == "Open") | |
| assert(closeOnClick == "CloseDoc()") | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment