changeset 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
files julia/parallel/ParallelProcessing/src/ParallelProcessing.jl julia/parallel/ParallelProcessing/src/json.jl julia/parallel/ParallelProcessing/src/jsonparser.jl
diffstat 3 files changed, 72 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/julia/parallel/ParallelProcessing/src/ParallelProcessing.jl	Sun Mar 19 20:04:34 2023 +0100
+++ b/julia/parallel/ParallelProcessing/src/ParallelProcessing.jl	Sun Mar 19 20:20:13 2023 +0100
@@ -1,5 +1,5 @@
 module ParallelProcessing
 
+include("jsonparser.jl")
 include("json.jl")
-include("jsonparser.jl")
 end # module ParallelProcessing
--- a/julia/parallel/ParallelProcessing/src/json.jl	Sun Mar 19 20:04:34 2023 +0100
+++ b/julia/parallel/ParallelProcessing/src/json.jl	Sun Mar 19 20:20:13 2023 +0100
@@ -7,6 +7,47 @@
     kind::Int
 end
 
+"""Example for a method that can be derived straight from a struct definition and parses just a struct
+            from a JSON object."""
+function take_struct!(t::Type{Details}, jp::JP)::Union{Nothing,Details}
+    expect!(jp, '{') || return nothing
+
+    level::Union{Nothing,String} = nothing
+    kind::Union{Nothing, Int} = nothing
+    while true
+        key = take_str!(jp)
+        if isnothing(key)
+            break
+        end
+
+        expect!(jp, ':') || error("malformed object - expected ':'")
+
+        # Custom code!
+        if key == "level"
+            level = take_str!(jp)
+        elseif key == "kind"
+            kind = take_num!(jp)
+        else
+            # Ignore unknown keys
+            take_val!(jp)
+        end
+
+        if expect!(jp, ',')
+            continue
+        else
+            break
+        end
+    end
+
+    if isnothing(level) || isnothing(kind)
+        error("Elements missing from object: $level, $kind")
+    end
+
+    expect!(jp, '}') || error("unclosed Details object")
+    
+    Details(level, kind)
+end
+
 struct SimpleEntry
     s::String
     a::Int
--- a/julia/parallel/ParallelProcessing/src/jsonparser.jl	Sun Mar 19 20:04:34 2023 +0100
+++ b/julia/parallel/ParallelProcessing/src/jsonparser.jl	Sun Mar 19 20:20:13 2023 +0100
@@ -31,6 +31,22 @@
     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
@@ -41,38 +57,38 @@
     end
 end
 
-function take_dict!(jp::JP)::Union{Nothing,Dict{String,Any}}
+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 dict
+            # Empty object
             break
         end
 
-        expect!(jp, ':') || error("malformatted dict - expecting ':'")
+        expect!(jp, ':') || error("malformatted object - expecting ':'")
 
-        val = take_obj!(jp)
+        val = take_val!(jp)
 
         d[key] = val
         if expect!(jp, ',')
             continue
         else
-            # End of dict
+            # End of object
             break
         end
     end
 
-    expect!(jp, '}') || error("Unclosed dict - '}' missing")
+    expect!(jp, '}') || error("Unclosed object - '}' missing")
     d
 end
 
 function take_str!(jp::JP)::Union{Nothing,String}
     expect!(jp, '"') || return nothing
 
-    span = takewhile!(jp, (!=)('"'))
+    span = takewhile!(jp, (!=)('"'), false)
     if isnothing(span)
         error("unclosed string at $(jp.pos)")
     end
@@ -87,7 +103,7 @@
 
     l = Any[]
     while true
-        o = take_obj!(jp)
+        o = take_val!(jp)
         if isnothing(o)
             break
         else
@@ -105,8 +121,9 @@
     l
 end
 
-function take_obj!(jp::JP)::Union{Nothing,Any}
-    d = take_dict!(jp)
+"""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
@@ -129,9 +146,10 @@
     nothing
 end
 
-function parse_object(s::AbstractString)
+"""Parse a json value.."""
+function parse_value(s::AbstractString)
     jp = JP(s)
-    take_obj!(jp)
+    take_val!(jp)
 end
 
 function takewhile!(jp::JP, pred::Function, stripws=true)::Union{Nothing,Tuple{Int,Int}}