Skip to content

Instantly share code, notes, and snippets.

@kddnewton
Last active October 6, 2023 09:25
Show Gist options
  • Star 44 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save kddnewton/cdd86ffab5235ea6abcb005978ded7e4 to your computer and use it in GitHub Desktop.
Save kddnewton/cdd86ffab5235ea6abcb005978ded7e4 to your computer and use it in GitHub Desktop.
JSON parser with pattern matching
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 /\A(true|false)/ then $1 == "true"
when /\Anull/ then nil
else raise
end
source = $'
end
def parse_array(tokens)
result = []
loop do
item, tokens = parse_item(tokens)
result << item
case tokens
in [:"]", *rest] then return result, rest
in [:",", *rest] then tokens = rest
end
end
end
def parse_object(tokens)
result = {}
loop do
tokens => [String => key, :":", *tokens]
value, tokens = parse_item(tokens)
result[key] = value
case tokens
in [:"}", *rest] then return result, rest
in [:",", *rest] then tokens = rest
end
end
end
def parse_item(tokens)
case tokens
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
end
def parse(tokens)
parse_item(tokens) => [value, []]
value
end
p struct
p parse(tokens)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment