Skip to content

Instantly share code, notes, and snippets.

@hikaMaeng
Last active September 11, 2019 04:19
Show Gist options
  • Save hikaMaeng/a00d3826cf4bde2922be81a9aee91ce2 to your computer and use it in GitHub Desktop.
Save hikaMaeng/a00d3826cf4bde2922be81a9aee91ce2 to your computer and use it in GitHub Desktop.
package ein.core.core
import ein.core.regex.eReg
interface ePrimitive {
companion object {
val EMPTY = ePrimitive("")
operator fun invoke(v:String) = eString(v)
operator fun invoke(v:Long) = eLong(v)
operator fun invoke(v:Double) = eDouble(v)
operator fun invoke(v:Boolean) = eBoolean(v)
fun store(v:String) = eStore(v)
fun record(v:String) = eRecord(v)
fun json(v:String) = eReg.json.parse(v)
}
}
class eString(val v:String):ePrimitive
class eLong(val v:Long):ePrimitive
class eDouble(val v:Double):ePrimitive
class eBoolean(val v:Boolean):ePrimitive
class eStore(val v:String):ePrimitive
class eRecord(val v:String):ePrimitive
class eJsonArray:MutableList<ePrimitive> by mutableListOf(), ePrimitive
class eJsonObject:MutableMap<String, ePrimitive> by mutableMapOf(), ePrimitive{
operator fun invoke(key:String) = invoke(key.split("."))
operator fun invoke(key:List<String>)= key.fold(this as ePrimitive){target, k->
when(target){
is eJsonObject->target[k]
is eJsonArray->target[k.toInt()]
else->null
} ?: throw Throwable("invalid key:$k")
}
}
package ein.core.regex
abstract class eReg(r:String){
internal val re = r.toRegex()
companion object{
val value = ein.core.regex.value
val json = ein.core.regex.json
}
}
package ein.core.regex
import ein.core.core.eJsonArray
import ein.core.core.eJsonObject
import ein.core.core.ePrimitive
object json{
private val atom = """\s*(\{[^\{\}\[\]]*\}|\[[^\{\}\[\]]*\])\s*""".toRegex(RegexOption.MULTILINE)
private val jsonAtomKey = """<@#([0-9]+)!\$>""".toRegex()
private val jsonKey = """^\s*("(?:[^":]*)"|(?:[^:,\s"`]+)|`(?:[^`:]*)`)\s*:""".toRegex()
fun parse(txt:String):ePrimitive{
if(txt.isBlank()) return ePrimitive.EMPTY
if(value.re.matches(txt)) return value(txt) ?: ePrimitive.EMPTY
val kv = mutableMapOf<String, String>()
var v = txt
var idx = 0
while(atom.find(v) != null) v = atom.replace(v) {
val k = "<@#${idx++}!$>"
kv.put(k, it.groupValues[1])
k
}
val map = mutableMapOf<String, ePrimitive>()
var last:ePrimitive = ePrimitive.EMPTY
kv.forEach {(k, v)->
var txt = v.substring(1, v.length - 1)
last = if(v[0] == '{') {
val obj = eJsonObject()
while(jsonKey.find(txt) != null){
val k = jsonKey.find(txt)?.groupValues?.get(1) ?: ""
txt = jsonKey.replaceFirst(txt, "")
if(value.re.find(txt) != null){
obj[k] = value(txt) ?: ePrimitive.EMPTY
txt = value.re.replaceFirst(txt, "")
}else if(jsonAtomKey.find(txt) != null){
obj[k] = map[jsonAtomKey.find(txt)?.groupValues?.get(0) ?: ""] ?: ePrimitive.EMPTY
txt = jsonAtomKey.replaceFirst(txt, "")
}else break
if(txt[0] == ',') txt = txt.substring(1) else break
}
obj
}else{
val arr = eJsonArray()
do{
if(value.re.find(txt) != null) {
arr += value(txt) ?: ePrimitive.EMPTY
txt = value.re.replaceFirst(txt, "")
}else if(jsonAtomKey.find(txt) != null){
arr += map[jsonAtomKey.find(txt)?.groupValues?.get(0) ?: ""] ?: ePrimitive.EMPTY
txt = jsonAtomKey.replaceFirst(txt, "")
}else break
if(txt[0] == ',') txt = txt.substring(1) else break
}while(true)
arr
}
map[k] = last
}
return last
}
}
package ein.core.regex
import ein.core.core.ePrimitive
object value: eReg("""^\s*""" +
//1,2-string
"""(?:"((?:[^\\"]+|\\["\\bfnrt]|\\u[0-9a-fA-invoke]{4})*)"|`((?:[^`]+|\\[`\\bfnrt]|\\u[0-9a-fA-invoke]{4})*)`|""" +
//3-long
"""(-?(?:0|[1-9]\d*)(?:dp|sp|%w|%h)?)|""" +
//4-double
"""(-?(?:0|[1-9]\d*)(?:\.\d+)(?:[eE][-+]?\d+)?(?:dp|%w|%h)?)|"""+
//5-bool
"""(true|false)|""" +
//6-store, 7-record
"""(?:\@\{([^}]+)\})|(?:\$\{([^}]*)\}))\s*"""
){
operator fun invoke(v:String) = re.find(v)?.let{
val g = it.groups
g[1]?.let{ePrimitive(it.value)} ?:
g[2]?.let{ePrimitive(it.value)} ?:
g[3]?.let{ePrimitive(group3(it))} ?:
g[4]?.let{ePrimitive(group4(it))} ?:
g[5]?.let{ePrimitive(it.value.toBoolean())} ?:
g[6]?.let{ePrimitive.store(it.value)} ?:
g[7]?.let{ePrimitive.record(it.value)}
}
fun group3(it:MatchGroup):Long{
val v = it.value
return when {
v.endsWith("dp")->(v.substring(0, v.length - 2).toDouble()).toLong()
v.endsWith("sp")->(v.substring(0, v.length - 2).toDouble()).toLong()
v.endsWith("%w")->(v.substring(0, v.length - 2).toDouble()).toLong()
v.endsWith("%h")->(v.substring(0, v.length - 2).toDouble()).toLong()
else->v.toLong()
}
}
fun group4(it:MatchGroup):Double{
val v = it.value
return when {
v.endsWith("dp") -> v.substring(0, v.length - 2).toDouble()
v.endsWith("sp") -> v.substring(0, v.length - 2).toDouble()
v.endsWith("%w") -> v.substring(0, v.length - 2).toDouble()
v.endsWith("%h") -> v.substring(0, v.length - 2).toDouble()
else -> v.toDouble()
}
}
fun num(it:String):Number? = re.find(it)?.let{it.groups[3]?.let{group3(it)} ?: it.groups[4]?.let{group4(it)}} as Number?
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment