On Feb 4, 2008, at 7:29 PM, James Gray wrote: > Here's my own recursive descent parser (based on the not-quite- > correct quiz tests): Finally, here's the JSON parser right out of Ghost Wheel's tests: #!/usr/bin/env ruby -wKU JSONParser = GhostWheel.build_parser( %q{ keyword = 'true' { true } | 'false' { false } | 'null' { nil } number = /-?(?:0|[1-9]\d*)(?:\.\d+(?:[eE][+-]?\d+)?)?/ { ast.include?(".") ? Float(ast) : Integer(ast) } string_content = /\\\\["\\\\\/]/ { ast[-1, 1] } | /\\\\[bfnrt]/ { Hash[*%W[b \n f \f n \n r \r t \t]][ast[-1, 1]] } | /\\\\u[0-9a-fA-F]{4}/ { [Integer("0x#{ast[2..-1]}")].pack("U") } | /[^\\\\"]+/ string = '"' string_content* '"' { ast.flatten[1..-2].join } array_content = value_with_array_sep+ value { ast[0].inject([]) { |a, v| a.push(*v) } + ast[-1..-1] } | value? { ast.is_a?(EmptyParseResult) ? [] : [ast] } array = /\[\s*/ array_content /\s*\]/ { ast[1] } object_pair = string /\s*:\s*/ value { {ast[0] => ast[-1]} } object_pair_and_sep = object_pair /\s*;\s*/ { ast[0] } object_content = object_pair_and_sep+ object_pair { ast.flatten } | object_pair? { ast.is_a?(EmptyParseResult) ? [] : [ast] } object = /\\\{\s*/ object_content /\\\}\s*/ { ast[1].inject({}) { |h, p| h.merge(p) } } value_space = /\s*/ value_content = keyword | number | string | array | object value = value_space value_content value_space { ast[1] } value_with_array_sep = value /\s*,\s*/ { ast[0] } json := value EOF { ast[0] } } ) __END__ James Edward Gray II