Last active
October 6, 2023 09:25
-
-
Save kddnewton/cdd86ffab5235ea6abcb005978ded7e4 to your computer and use it in GitHub Desktop.
JSON parser with pattern matching
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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