aboutsummaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorMatthew Hall <hallmatthew314@gmail.com>2023-04-04 21:39:53 +1200
committerMatthew Hall <hallmatthew314@gmail.com>2023-04-04 21:39:53 +1200
commit1888a8b5ea6316724bef2ca7a3d7b5d61707bd96 (patch)
treeb6468def2f75a5a92b9b3d29c663b209c75602d3 /spec
parent8ad9b4b0a05ae9aa080ff8ca1b02db9c94251dea (diff)
Add readme example as a test case
Diffstat (limited to 'spec')
-rw-r--r--spec/practical/int_int_hash_spec.cr92
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
+