Skip to content

Instantly share code, notes, and snippets.

@kddnewton
Last active December 18, 2024 17:34
Show Gist options
  • Save kddnewton/cdd86ffab5235ea6abcb005978ded7e4 to your computer and use it in GitHub Desktop.
Save kddnewton/cdd86ffab5235ea6abcb005978ded7e4 to your computer and use it in GitHub Desktop.

Revisions

  1. kddnewton revised this gist Jun 10, 2022. 1 changed file with 5 additions and 11 deletions.
    16 changes: 5 additions & 11 deletions json.rb
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,6 @@
    require "json"

    struct = { a: 1, b: 2, c: [1, 2, 3], d: [{ e: 3 }, nil, false, true, [], {}] }
    struct = { "a" => 1, "b" => 2, "c" => [1, 2, 3], "d" => [{ "e" => 3 }, nil, false, true, [], {}] }
    source = JSON.dump(struct)

    tokens = []
    @@ -22,9 +22,6 @@

    def parse_array(tokens)
    result = []
    if tokens in [:"]", *rest]
    return result, rest
    end

    loop do
    item, tokens = parse_item(tokens)
    @@ -39,9 +36,6 @@ def parse_array(tokens)

    def parse_object(tokens)
    result = {}
    if tokens in [:"}", *rest]
    return result, rest
    end

    loop do
    tokens => [String => key, :":", *tokens]
    @@ -57,10 +51,10 @@ def parse_object(tokens)

    def parse_item(tokens)
    case tokens
    in [:"[", *rest]
    parse_array(rest)
    in [:"{", *rest]
    parse_object(rest)
    in [:"[", :"]", *rest] then [[], rest]
    in [:"[", *rest] then parse_array(rest)
    in [:"{", :"}", *rest] then [{}, rest]
    in [:"{", *rest] then parse_object(rest)
    in [FalseClass | Integer | NilClass | String | TrueClass => value, *rest]
    [value, rest]
    end
  2. kddnewton revised this gist Jun 10, 2022. 1 changed file with 42 additions and 35 deletions.
    77 changes: 42 additions & 35 deletions json.rb
    Original file line number Diff line number Diff line change
    @@ -10,59 +10,66 @@
    tokens <<
    case source.strip
    when /\A[\{\}\[\],:]/ then $&.to_sym
    when /\A(\d+)/ then $1.to_i
    when /\A"([^"]*?)"/ then $1
    when /\Anull/ then nil
    when /\Atrue/ then true
    when /\Afalse/ then false
    else
    raise
    when /\A(\d+)/ then $1.to_i
    when /\A"([^"]*?)"/ then $1
    when /\A(true|false)/ then $1 == "true"
    when /\Anull/ then nil
    else raise
    end

    source = $'
    end

    def parse_item(tokens)
    case tokens
    in [:"{", *rest]
    count = 1
    index = rest.index { (count += { "{": 1, "}": -1 }.fetch(_1, 0)) == 0 }
    [parse_object(rest[0...index]), rest[(index + 1)..]]
    in [:"[", *rest]
    count = 1
    index = rest.index { (count += { "[": 1, "]": -1 }.fetch(_1, 0)) == 0 }
    [parse_array(rest[0...index]), rest[(index + 1)..]]
    in [value, *rest]
    [value, rest]
    def parse_array(tokens)
    result = []
    if tokens in [:"]", *rest]
    return result, rest
    end
    end

    def parse_object(tokens)
    return {} if tokens in []
    tokens => [String => key, :":", *rest]
    loop do
    item, tokens = parse_item(tokens)
    result << item

    case parse_item(rest)
    in item, [:",", *rest] then { key => item }.merge(parse_object(rest))
    in item, [] then { key => item }
    case tokens
    in [:"]", *rest] then return result, rest
    in [:",", *rest] then tokens = rest
    end
    end
    end

    def parse_array(tokens)
    return [] if tokens in []
    def parse_object(tokens)
    result = {}
    if tokens in [:"}", *rest]
    return result, rest
    end

    loop do
    tokens => [String => key, :":", *tokens]
    value, tokens = parse_item(tokens)
    result[key] = value

    case parse_item(tokens)
    in item, [:",", *rest] then [item] + parse_array(rest)
    in left, [] then [item]
    case tokens
    in [:"}", *rest] then return result, rest
    in [:",", *rest] then tokens = rest
    end
    end
    end

    def parse(tokens)
    def parse_item(tokens)
    case tokens
    in [:"{", *rest, :"}"] then parse_object(rest)
    in [:"[", *rest, :"]"] then parse_array(rest)
    in [value] then value
    in [:"[", *rest]
    parse_array(rest)
    in [:"{", *rest]
    parse_object(rest)
    in [FalseClass | Integer | NilClass | String | TrueClass => value, *rest]
    [value, rest]
    end
    end

    def parse(tokens)
    parse_item(tokens) => [value, []]
    value
    end

    p struct
    p parse(tokens)
  3. kddnewton created this gist Jun 10, 2022.
    68 changes: 68 additions & 0 deletions json.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,68 @@
    require "json"

    struct = { a: 1, b: 2, c: [1, 2, 3], d: [{ e: 3 }, nil, false, true, [], {}] }
    source = JSON.dump(struct)

    tokens = []
    index = 0

    until source.empty?
    tokens <<
    case source.strip
    when /\A[\{\}\[\],:]/ then $&.to_sym
    when /\A(\d+)/ then $1.to_i
    when /\A"([^"]*?)"/ then $1
    when /\Anull/ then nil
    when /\Atrue/ then true
    when /\Afalse/ then false
    else
    raise
    end

    source = $'
    end

    def parse_item(tokens)
    case tokens
    in [:"{", *rest]
    count = 1
    index = rest.index { (count += { "{": 1, "}": -1 }.fetch(_1, 0)) == 0 }
    [parse_object(rest[0...index]), rest[(index + 1)..]]
    in [:"[", *rest]
    count = 1
    index = rest.index { (count += { "[": 1, "]": -1 }.fetch(_1, 0)) == 0 }
    [parse_array(rest[0...index]), rest[(index + 1)..]]
    in [value, *rest]
    [value, rest]
    end
    end

    def parse_object(tokens)
    return {} if tokens in []
    tokens => [String => key, :":", *rest]

    case parse_item(rest)
    in item, [:",", *rest] then { key => item }.merge(parse_object(rest))
    in item, [] then { key => item }
    end
    end

    def parse_array(tokens)
    return [] if tokens in []

    case parse_item(tokens)
    in item, [:",", *rest] then [item] + parse_array(rest)
    in left, [] then [item]
    end
    end

    def parse(tokens)
    case tokens
    in [:"{", *rest, :"}"] then parse_object(rest)
    in [:"[", *rest, :"]"] then parse_array(rest)
    in [value] then value
    end
    end

    p struct
    p parse(tokens)