require "./lexer" class JSON::Parser property max_nesting = 512 def initialize(string_or_io : String | IO) @lexer = JSON::Lexer.new(string_or_io) @nest = 0 next_token end def parse : Any json = parse_value check :EOF json end private def parse_value case token.kind when .int? value_and_next_token token.int_value when .float? value_and_next_token token.float_value when .string? value_and_next_token token.string_value when .null? value_and_next_token nil when .true? value_and_next_token true when .false? value_and_next_token false when .begin_array? parse_array when .begin_object? parse_object else unexpected_token end end private def parse_array next_token ary = [] of Any nest do unless token.kind.end_array? while true ary << parse_value case token.kind when .comma? next_token unexpected_token if token.kind.end_array? when .end_array? break else unexpected_token end end end end next_token Any.new(ary) end private def parse_object next_token_expect_object_key object = {} of String => Any nest do unless token.kind.end_object? while true check :string key = token.string_value next_token check :colon next_token value = parse_value object[key] = value case token.kind when .comma? next_token_expect_object_key unexpected_token if token.kind.end_object? when .end_object? break else unexpected_token end end end end next_token Any.new(object) end private delegate token, to: @lexer private delegate next_token, to: @lexer private delegate next_token_expect_object_key, to: @lexer private def value_and_next_token(value) next_token Any.new(value) end private def check(kind : Token::Kind) unexpected_token unless token.kind == kind end private def unexpected_token parse_exception "unexpected token '#{token}'" end private def parse_exception(msg) raise ParseException.new(msg, token.line_number, token.column_number) end private def nest(&) @nest += 1 if @nest > @max_nesting parse_exception "Nesting of #{@nest} is too deep" end yield @nest -= 1 end end