Mercurial > lbo > hg > juliaplay
view julia/parallel/ParallelProcessing/src/jsonparser.jl @ 33:2d033830c26e
Implement struct-specific parser
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Sun, 19 Mar 2023 20:20:13 +0100 |
parents | 3d916aa02d00 |
children | a36e3e66ae3e |
line wrap: on
line source
mutable struct JP s::String pos::Int end function JP(s::AbstractString)::JP JP(string(s), 1) end function current(jp::JP)::Char jp.s[jp.pos] end function next!(jp::JP) jp.pos += 1 end function isend(jp::JP) jp.pos > length(jp.s) end function take_num!(jp::JP)::Union{Nothing,Float64} pred(c) = isdigit(c) || (c == '.') # todo: exponential numbers span = takewhile!(jp, pred) if isnothing(span) nothing else a, b = span parse(Float64, (@view jp.s[a:b])) end end function take_num!(jp::JP)::Union{Nothing,Float64,Int} pred(c) = isdigit(c) || (c == '-') || (c == '.') # todo: exponential numbers span = takewhile!(jp, pred) if isnothing(span) nothing else a, b = span s = (@view jp.s[a:b]) if contains(s, '.') parse(Float64, s) else parse(Int, s) end end end function take_bool!(jp::JP)::Union{Nothing,Bool} if expect_prefix!(jp, "true") true elseif expect_prefix!(jp, "false") false else nothing end end function take_object!(jp::JP)::Union{Nothing,Dict{String,Any}} expect!(jp, '{') || return nothing d = Dict{String,Any}() while true key = take_str!(jp) if isnothing(key) # Empty object break end expect!(jp, ':') || error("malformatted object - expecting ':'") val = take_val!(jp) d[key] = val if expect!(jp, ',') continue else # End of object break end end expect!(jp, '}') || error("Unclosed object - '}' missing") d end function take_str!(jp::JP)::Union{Nothing,String} expect!(jp, '"') || return nothing span = takewhile!(jp, (!=)('"'), false) if isnothing(span) error("unclosed string at $(jp.pos)") end expect!(jp, '"') || error("unclosed string at $(jp.pos)") a, b = span jp.s[a:b] end function take_list!(jp::JP)::Union{Nothing,Vector{Any}} expect!(jp, '[') || return nothing l = Any[] while true o = take_val!(jp) if isnothing(o) break else push!(l, o) end if expect!(jp, ',') continue else break end end expect!(jp, ']') || error("Missing closing ']' at $(jp.pos)") l end """value is anything - object/list/number/boolean/string""" function take_val!(jp::JP)::Union{Nothing,Any} d = take_object!(jp) if !isnothing(d) return d end n = take_num!(jp) if !isnothing(n) return n end s = take_str!(jp) if !isnothing(s) return s end b = take_bool!(jp) if !isnothing(b) return b end l = take_list!(jp) if !isnothing(l) return l end nothing end """Parse a json value..""" function parse_value(s::AbstractString) jp = JP(s) take_val!(jp) end function takewhile!(jp::JP, pred::Function, stripws=true)::Union{Nothing,Tuple{Int,Int}} if stripws strip_ws!(jp) end if !isend(jp) && pred(current(jp)) a = jp.pos b = a while !isend(jp) && pred(current(jp)) next!(jp) b += 1 end (a, b-1) else nothing end end function strip_ws!(jp::JP) while !isend(jp) && isspace(jp.s[jp.pos]) jp.pos += 1 end end function expect!(jp::JP, c::Char)::Bool strip_ws!(jp) if current(jp) == c next!(jp) true else false end end function expect_prefix!(jp::JP, pref::AbstractString)::Bool strip_ws!(jp) if (@view jp.s[jp.pos:min(length(jp.s), jp.pos+length(pref)-1)]) == pref jp.pos += length(pref) true else false end end