require "../spec_helper" include Parcom # NOTE: WORK IN PROGRESS alias JSONType = Nil \ | Bool \ | Int64 \ | Float64 \ | String \ | Array(JSONValue) \ | Hash(String, JSONValue) struct JSONValue property data : JSONType def initialize(@data) end end def json_null Parser.token_sequence("null".chars).map { |_| JSONValue.new(nil) } end def json_bool t = Parser.token_sequence("true".chars).map { |_| true } f = Parser.token_sequence("false".chars).map { |_| false } (t | f).map { |b| JSONValue.new(b) } end # Only standard decimal ints for now def json_number base_num = Parser(Char, Char).satisfy(&.ascii_number?).some.map do |cs| cs.join.to_i64 end sign = Parser.token('-').map { |_| -1 }.recover(1) (sign + base_num).map { |s, n| JSONValue.new(s.to_i64 * n) } end def json_value : Parser(Char, JSONValue) Parser.first_of([ json_null, json_bool, json_number, ]) end describe "example: JSON parsing" do describe "json_null" do it "parses the string 'null' and returns nil when successful" do result = json_null.parse(Tokens.from_string("null")) result.value.data.should be_nil result.tokens.empty?.should be_true expect_raises(ParserFail) { json_null.parse(Tokens.from_string("")) } end end describe "json_bool" do it "parses the strings 'true' or 'false' and returns bool" do result = json_bool.parse(Tokens.from_string("true")) result.value.data.should be_true result.tokens.empty?.should be_true result = json_bool.parse(Tokens.from_string("false")) result.value.data.should be_false result.tokens.empty?.should be_true expect_raises(ParserFail) { json_bool.parse(Tokens.from_string("")) } end end describe "json_number" do it "parses strings of digits and other key characters and converts to number" do result = json_number.parse(Tokens.from_string("42")) result.value.data.should eq(42) result.tokens.empty?.should be_true result = json_number.parse(Tokens.from_string("-42")) result.value.data.should eq(-42) result.tokens.empty?.should be_true expect_raises(ParserFail) { json_number.parse(Tokens.from_string("")) } expect_raises(ParserFail) { json_number.parse(Tokens.from_string("foo")) } end end describe "json_value" do it "parses null" do result = json_value.parse(Tokens.from_string("null")) result.value.data.should be_nil result.tokens.empty?.should be_true end it "parses bools" do result = json_value.parse(Tokens.from_string("true")) result.value.data.should be_true result.tokens.empty?.should be_true result = json_value.parse(Tokens.from_string("false")) result.value.data.should be_false result.tokens.empty?.should be_true end it "parsers ints" do result = json_value.parse(Tokens.from_string("42")) result.value.data.should eq(42) result.tokens.empty?.should be_true result = json_value.parse(Tokens.from_string("-42")) result.value.data.should eq(-42) result.tokens.empty?.should be_true end end end