increase parser perf by a lot
This commit is contained in:
@@ -1,37 +1,38 @@
|
||||
package blitz.parse
|
||||
|
||||
import blitz.collections.RefVec
|
||||
import blitz.parse.comb2.*
|
||||
import org.json.JSONObject
|
||||
import kotlin.math.min
|
||||
import kotlin.system.measureNanoTime
|
||||
|
||||
object JSON {
|
||||
|
||||
val jsonBool: Parser<Char, Element> = choose {
|
||||
it(mapValue(seq("true".toList())) { Element.newBool(true) })
|
||||
it(mapValue(seq("false".toList())) { Element.newBool(false) })
|
||||
}
|
||||
|
||||
val jsonNull: Parser<Char, Element> =
|
||||
mapValue(seq("null".toList())) { Element.newNull() }
|
||||
|
||||
val jsonNum: Parser<Char, Element> =
|
||||
mapValue(floatLit, Element::newNum)
|
||||
|
||||
val jsonString: Parser<Char, Element> =
|
||||
mapValue(stringLit, Element::newStr)
|
||||
|
||||
val jsonElement = futureRec { jsonElement: Parser<Char, Element> ->
|
||||
|
||||
val jsonNum: Parser<Char, Element> =
|
||||
mapValue(floatLit(), ::Number)
|
||||
|
||||
val jsonString: Parser<Char, Element> =
|
||||
mapValue(stringLit(), ::Str)
|
||||
|
||||
val jsonArray: Parser<Char, Element> =
|
||||
thenIgnore(
|
||||
thenIgnore(
|
||||
thenOverwrite(just('['),
|
||||
mapValue(delimitedBy(jsonElement, just(',')))
|
||||
{ Array(it.toList())}),
|
||||
whitespaces()),
|
||||
mapValue(delimitedBy(jsonElement, just(',')), Element::newArr)),
|
||||
whitespaces),
|
||||
just(']')
|
||||
)
|
||||
|
||||
val jsonBool: Parser<Char, Element> = choose(
|
||||
mapValue(seq("true".toList())) { Bool(true) },
|
||||
mapValue(seq("false".toList())) { Bool(false) },
|
||||
)
|
||||
|
||||
val jsonNull: Parser<Char, Element> =
|
||||
mapValue(seq("null".toList())) { Nul() }
|
||||
|
||||
val jsonObj: Parser<Char, Element> =
|
||||
mapValue(thenIgnore(thenIgnore(thenOverwrite(
|
||||
just('{'),
|
||||
@@ -40,74 +41,99 @@ object JSON {
|
||||
thenIgnore(
|
||||
thenIgnore(
|
||||
thenOverwrite(
|
||||
whitespaces(),
|
||||
stringLit()),
|
||||
whitespaces()),
|
||||
whitespaces,
|
||||
stringLit),
|
||||
whitespaces),
|
||||
just(':')),
|
||||
jsonElement),
|
||||
just(','))),
|
||||
whitespaces()),
|
||||
just('}'))) { Obj(it.toMap()) }
|
||||
whitespaces),
|
||||
just('}'))) { Element.newObj(it.toMap()) }
|
||||
|
||||
thenIgnore(thenOverwrite(
|
||||
whitespaces(),
|
||||
choose(
|
||||
jsonArray,
|
||||
jsonNum,
|
||||
jsonString,
|
||||
jsonObj,
|
||||
jsonBool,
|
||||
jsonNull
|
||||
)),
|
||||
whitespaces())
|
||||
whitespaces,
|
||||
choose {
|
||||
it(jsonArray)
|
||||
it(jsonNum)
|
||||
it(jsonString)
|
||||
it(jsonObj)
|
||||
it(jsonBool)
|
||||
it(jsonNull)
|
||||
}),
|
||||
whitespaces)
|
||||
|
||||
}
|
||||
|
||||
interface Element {
|
||||
val arr get() = (this as Array).value
|
||||
val num get() = (this as Number).value
|
||||
val str get() = (this as Str).value
|
||||
val obj get() = (this as Obj).value
|
||||
val bool get() = (this as Bool).value
|
||||
class Element(
|
||||
@JvmField val kind: Int,
|
||||
@JvmField val _boxed: Any? = null,
|
||||
@JvmField val _num: Double = 0.0,
|
||||
@JvmField val _bool: Boolean = false,
|
||||
) {
|
||||
companion object {
|
||||
const val NUM = 0
|
||||
const val BOOL = 1
|
||||
const val NULL = 2
|
||||
const val ARR = 3
|
||||
const val STR = 4
|
||||
const val OBJ = 5
|
||||
|
||||
fun isArr() = this is Array
|
||||
fun isNum() = this is Number
|
||||
fun isStr() = this is Str
|
||||
fun isObj() = this is Obj
|
||||
fun isBool() = this is Bool
|
||||
fun isNul() = this is Nul
|
||||
inline fun newNum(v: Double): Element =
|
||||
Element(NUM, _num = v)
|
||||
inline fun newBool(v: Boolean): Element =
|
||||
Element(BOOL, _bool = v)
|
||||
inline fun newNull(): Element =
|
||||
Element(NULL)
|
||||
inline fun newArr(v: RefVec<Element>): Element =
|
||||
Element(ARR, _boxed = v)
|
||||
inline fun newStr(v: String): Element =
|
||||
Element(STR, _boxed = v)
|
||||
inline fun newObj(v: Map<String, Element>): Element =
|
||||
Element(OBJ, _boxed = v)
|
||||
}
|
||||
}
|
||||
|
||||
inline fun Element.uncheckedAsNum(): Double =
|
||||
_num
|
||||
inline fun Element.uncheckedAsBool(): Boolean =
|
||||
_bool
|
||||
inline fun Element.uncheckedAsArr(): RefVec<Element> =
|
||||
_boxed as RefVec<Element>
|
||||
inline fun Element.uncheckedAsStr(): String =
|
||||
_boxed as String
|
||||
inline fun Element.uncheckedAsObj(): Map<String, Element> =
|
||||
_boxed as Map<String, Element>
|
||||
|
||||
inline fun Element.asNum(): Double {
|
||||
require(kind == Element.NUM) { "Element is not a Number" }
|
||||
return _num
|
||||
}
|
||||
|
||||
data class Array(val value: List<Element>): Element {
|
||||
override fun toString(): String =
|
||||
value.joinToString(separator = ", ", prefix = "[", postfix = "]")
|
||||
inline fun Element.asBool(): Boolean {
|
||||
require(kind == Element.BOOL) { "Element is not a Boolean" }
|
||||
return _bool
|
||||
}
|
||||
|
||||
data class Number(val value: Double): Element {
|
||||
override fun toString(): String =
|
||||
value.toString()
|
||||
inline fun Element.asArr(): RefVec<Element> {
|
||||
require(kind == Element.ARR) { "Element is not an Array" }
|
||||
return _boxed as RefVec<Element>
|
||||
}
|
||||
|
||||
data class Str(val value: String): Element {
|
||||
override fun toString(): String =
|
||||
"\"$value\""
|
||||
inline fun Element.asStr(): String {
|
||||
require(kind == Element.STR) { "Element is not a String" }
|
||||
return _boxed as String
|
||||
}
|
||||
|
||||
data class Obj(val value: Map<String, Element>): Element {
|
||||
override fun toString(): String =
|
||||
value.map { (k, v) -> "\"$k\": $v" }.joinToString(separator = ", ", prefix = "{", postfix = "}")
|
||||
inline fun Element.asObj(): Map<String, Element> {
|
||||
require(kind == Element.OBJ) { "Element is not an Object" }
|
||||
return _boxed as Map<String, Element>
|
||||
}
|
||||
|
||||
|
||||
data class Bool(val value: Boolean): Element {
|
||||
override fun toString(): String =
|
||||
value.toString()
|
||||
fun parse(string: String): ParseResult<Element> {
|
||||
val ctx = ParseCtx(string.toList(), 0)
|
||||
val v = jsonElement(ctx)
|
||||
return v
|
||||
}
|
||||
|
||||
class Nul: Element
|
||||
|
||||
fun parse(string: String): ParseResult<Element> =
|
||||
jsonElement(ParseCtx(string.toList(), 0))
|
||||
}
|
||||
|
||||
fun main() {
|
||||
|
Reference in New Issue
Block a user