diff options
Diffstat (limited to 'spec')
| -rw-r--r-- | spec/practical/int_int_hash_spec.cr | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/spec/practical/int_int_hash_spec.cr b/spec/practical/int_int_hash_spec.cr new file mode 100644 index 0000000..4d4ce0c --- /dev/null +++ b/spec/practical/int_int_hash_spec.cr @@ -0,0 +1,92 @@ +require "../spec_helper" + +include Parcom + +describe "Hash(Int32, Int32) parser", tags: "example" do + # setup + d = Parser(Char, Char).satisfy(&.number?).named("digit") + abs_num = d.some.map { |ds| ds.join.to_i32 }.named("abs_num") + + sign = Parser.token('-').map_const(-1_i32).recover(1_i32).named("sign") + + int32 = parser_chain Char, Int32, "int32", + {s, sign}, + {n, abs_num}, + pure: n * s + + ws = Parser(Char, Char).satisfy(&.whitespace?) + .many + .named("whitespace") + + arrow = (ws >> Parser.token_sequence("=>".chars) >> ws).named("arrow") + + pair = parser_chain Char, {Int32, Int32}, "pair", + {x, int32}, + {_, arrow}, + {y, int32}, + pure: {x, y} + + delim = (ws >> Parser.token(',') >> ws).named("delim") + + elements = parser_chain Char, Array({Int32, Int32}), "elements", + {pairs, pair.sep_by(delim)}, + {_, delim.optional}, # trailing comma + pure: pairs + + hash_start = (Parser.token('{') >> ws).named("start") + hash_end = (ws >> Parser.token('}')).named("end") + + hash = parser_chain Char, Hash(Int32, Int32), "hash", + {_, hash_start}, + {es, elements.recover([] of {Int32, Int32})}, + {_, hash_end}, + pure: es.to_h + + it "can parse an empty hash" do + empty = {} of Int32 => Int32 + + {"{}", "{ }", "{ \t\n\r}"}.each do |s| + result = hash.parse(Tokens.from_string(s)) + result.value.should eq(empty) + result.tokens.empty?.should be_true + end + end + + it "does not accept trailing commas in empty hashes" do + {"{,}", "{ ,}", "{, }", "{ , }"}.each do |s| + expect_raises(ParserFail) { hash.parse(Tokens.from_string(s)) } + end + end + + it "can parse hashes with one entry" do + expected = {2_i32 => -1_i32} + { + "{2=>-1}", + "{2=>-1,}", + "{2 =>-1 ,}", + "{ 2 => -1 , }", + }.each do |s| + result = hash.parse(Tokens.from_string(s)) + result.value.should eq(expected) + result.tokens.empty?.should be_true + end + end + + it "can parse hashes with many entries" do + expected = { + -2_i32 => 1_i32, + 3_i32 => -45_i32, + -6_i32 => -7_i32, + 8_i32 => 90_i32, + } + { + "{-2=>1,3=>-45,-6=>-7,8=>90}", + "{ -2=> 1,3 => -45,-6 =>-7,8 => 90,}", + }.each do |s| + result = hash.parse(Tokens.from_string(s)) + result.value.should eq(expected) + result.tokens.empty?.should be_true + end + end +end + |
