aboutsummaryrefslogtreecommitdiff
path: root/spec/parcom_spec.cr
diff options
context:
space:
mode:
authorMatthew Hall <hallmatthew314@gmail.com>2023-03-16 23:11:23 +1300
committerMatthew Hall <hallmatthew314@gmail.com>2023-03-16 23:11:23 +1300
commitf023ca56dbf9372464afe0060270fcef85271db0 (patch)
treeb045bebfbb8ac7e6208e5703cb0f53808b14fe89 /spec/parcom_spec.cr
parentb274828831fec26cd8b3089ffef14cb96ce2de2f (diff)
I'm too tired for this
Diffstat (limited to 'spec/parcom_spec.cr')
-rw-r--r--spec/parcom_spec.cr170
1 files changed, 169 insertions, 1 deletions
diff --git a/spec/parcom_spec.cr b/spec/parcom_spec.cr
index d25c786..ceb7de8 100644
--- a/spec/parcom_spec.cr
+++ b/spec/parcom_spec.cr
@@ -4,6 +4,174 @@ require "../src/parcom.cr"
include Parcom
-pending State do
+describe Tokens do
+ describe ".from_string" do
+ it "constructs a Tokens(Char) from a String" do
+ tokens = Tokens.from_string("abcd")
+ tokens.tokens.should eq("abcd".chars)
+ end
+ end
+
+ describe "#initialize" do
+ it "wraps an array with the contents of the given iterable" do
+ set = Set{'a', 'b', 'c', 'd'}
+ tokens = Tokens.new(set)
+ tokens.tokens.should eq(set.to_a)
+
+ arr = "abcd".chars
+ tokens = Tokens.new(arr)
+ tokens.tokens.should eq(arr)
+ end
+ end
+
+ context do
+ tokens_empty = Tokens.new([] of Char)
+ tokens = Tokens.from_string("abcd")
+
+ describe "#[]" do
+ it "returns the token at the given index" do
+ tokens[2].should eq('c')
+ expect_raises(IndexError) { tokens_empty[2] }
+ end
+
+ it "returns a new Tokens similar to Array#[](Int, Int)" do
+ tokens[1, 5].should eq(Tokens.new(['b', 'c', 'd']))
+ expect_raises(IndexError) { tokens_empty[1, 5] }
+ end
+
+ it "returns a new Tokens similar to Array#[](Range)" do
+ tokens[1..3].should eq(Tokens.new(['b', 'c', 'd']))
+ expect_raises(IndexError) { tokens_empty[1..3] }
+ end
+ end
+
+ describe "#[]?" do
+ it "analogous to `Array#[]?`" do
+ # we should only need to check the nil-returning cases
+ tokens_empty[2]?.should be_nil
+ tokens_empty[1, 5]?.should be_nil
+ tokens_empty[1..3]?.should be_nil
+ end
+ end
+
+ describe "#empty?" do
+ it "exposes the `#empty?` method of the wrapped array" do
+ tokens.empty?.should be_false
+ tokens_empty.empty?.should be_true
+ end
+ end
+ end
+end
+
+describe Result do
+ describe "#map" do
+ r = Result.new(Tokens.from_string("abcd"), 'x')
+ r_expected = Result.new(Tokens.from_string("abcd"), 'x'.ord)
+
+ it "accepts a proc" do
+ f = ->(c : Char) { c.ord }
+ r.map(f).should eq(r_expected)
+ end
+
+ it "accepts a block" do
+ r.map { |c| c.ord }.should eq(r_expected)
+ end
+ end
+end
+
+pending Parser do
+ describe "#assert" do
+ p = Basic(Char, Char).any_token.assert { |c| c == 'a' }
+
+ it "succeeds if the parser succeeds and if the predicate passes" do
+ tokens = Tokens.from_string("abcd")
+ result = p.parse(tokens)
+
+ result.value.should eq(tokens[0])
+ result.tokens.should eq(tokens[1..])
+ end
+
+ it "fails if the predicate fails" do
+ tokens = Tokens.from_string("bbcd")
+ expect_raises(ParserFail) { p.parse(tokens) }
+ end
+ end
+end
+
+describe Basic do
+ describe "Basic.pure" do
+ v = 'a'
+ p = Basic(Char, Char).pure(v)
+ tokens = Tokens.from_string("____")
+ result = p.parse(tokens)
+
+ it "returns a value of whatever it was initialized with" do
+ result.value.should eq(v)
+ end
+
+ it "does not modify the input" do
+ result.tokens.should eq(tokens)
+ end
+ end
+
+ describe "Basic.flunk" do
+ p = Basic(Char, Char).flunk
+ it "always fails" do
+ expect_raises(ParserFail) { p.parse(Tokens.from_string("arbitrary")) }
+ end
+ end
+
+ describe "Basic.any_token" do
+ p = Basic(Char, Nil).any_token
+
+ it "parses the first token in the input stream" do
+ tokens = Tokens.from_string("abcd")
+ result = p.parse(tokens)
+
+ result.value.should eq(tokens[0])
+ result.tokens.should eq(tokens[1..])
+ end
+
+ it "fails if the input stream is empty" do
+ tokens = Tokens.from_string("")
+ expect_raises(ParserFail) { p.parse(tokens) }
+ end
+ end
+
+ describe "Basic.eof" do
+ p = Basic(Char, Nil).eof
+
+ it "succeeds with nil if the input stream is empty" do
+ tokens = Tokens.from_string("")
+ result = p.parse(tokens)
+
+ result.value.should be_nil
+ result.tokens.empty?.should be_true
+ end
+
+ it "fails if the input stream is not empty" do
+ tokens = Tokens.from_string("____")
+ expect_raises(ParserFail) { p.parse(tokens) }
+ end
+ end
+
+ # TODO: the type checker hates me
+ describe "Basic.satisfy" do
+ #p = Basic.satisfy(Char) { |c| c == 'a' }
+ p = Basic(Char, Char).satisfy(->(c : Char) { c == 'a' })
+
+ it "succeeds if the token passes the predicate" do
+ tokens = Tokens.from_string("abcd")
+ result = p.parse(tokens).as_a(Result(Char, Char))
+
+ result.value.should eq(tokens[0])
+ result.tokens.should eq(tokens[1..])
+ end
+
+ it "fails if the token fails the predicate" do
+ tokens = Tokens.from_string("bbcd")
+ expect_raises(ParserFail) { p.parse(tokens) }
+ end
+ end
end