From 14013d04f5023e68b5a804c3735e909241795878 Mon Sep 17 00:00:00 2001 From: Matthew Hall Date: Tue, 7 Mar 2023 01:30:02 +1300 Subject: Initial --- spec/parcom_spec.cr | 183 ++++++++++++++++++++++++++++++++++++++++++++++++++++ spec/spec_helper.cr | 2 + 2 files changed, 185 insertions(+) create mode 100644 spec/parcom_spec.cr create mode 100644 spec/spec_helper.cr (limited to 'spec') diff --git a/spec/parcom_spec.cr b/spec/parcom_spec.cr new file mode 100644 index 0000000..a496a3f --- /dev/null +++ b/spec/parcom_spec.cr @@ -0,0 +1,183 @@ +require "./spec_helper" + +require "../src/parcom.cr" + +include Parcom + +describe Result do + describe "#initialize" do + it "sets values for #tokens and #value" do + tokens = "esting".chars + value = 't' + result = Result(Char, Char).new(tokens, value) + + result.tokens.should eq(tokens) + result.value.should eq(value) + end + end +end + +describe Parser do + describe "#|" do + it "creates an `Alt` instance from `self` and another `Parser(T, V)`" do + p = AnyToken(Char).new | AnyToken(Char).new + + p.should be_a(Alt(Char, Char)) + end + end + + describe "#assert" do + it "creates an `Assert` instance from self and a `Proc(T, Bool)`" do + f = ->(x : Char) { x == '#' } + p = AnyToken(Char).new.assert(f) + + p.should be_a(Assert(Char, Char)) + end + end +end + +describe Flunk do + describe "#parse" do + it "always fails" do + tokens = "testing".chars + expect_raises(ParserException) { Flunk(Char, Char).new.parse(tokens) } + end + end +end + +describe AnyToken do + describe "#parse" do + it "succeeds when input is non-empty" do + tokens = "testing".chars + result = AnyToken(Char).new.parse(tokens) + + result.tokens.should eq(tokens[1..]) + result.value.should eq('t') + end + + it "fails when input is empty" do + expect_raises(ParserException) { AnyToken(Char).new.parse([] of Char) } + end + end +end + +describe Eof do + describe "#parse" do + it "succeeds when input is empty" do + result = Eof(Char).new.parse([] of Char) + + result.tokens.empty?.should be_true + result.value.should be_nil + end + + it "fails when input is non-empty" do + tokens = "testing".chars + + expect_raises(ParserException) { Eof(Char).new.parse(tokens) } + end + end +end + +describe Peek do + describe "#parse" do + it "does not modify the result of the wrapped parser" do + tokens = "testing".chars + parser = AnyToken(Char).new + result_normal = parser.parse(tokens) + result_peek = Peek.new(parser).parse(tokens) + + result_peek.value.should eq(result_normal.value) + end + + it "does not consume any input" do + tokens = "testing".chars + parser = AnyToken(Char).new + result = Peek.new(parser).parse(tokens) + + result.tokens.should eq(tokens) + end + end +end + +describe Assert do + describe "#parse" do + it "fails if the wrapped parser fails" do + test = ->(x : Char) { true } # doesn't matter for this test + p = Assert.new(AnyToken(Char).new, test) + expect_raises(ParserException) { p.parse([] of Char) } + end + + it "fails if the result value fails the test" do + tokens = "testing".chars + test = ->(x : Char) { x == '$' } + p = Assert.new(AnyToken(Char).new, test) + expect_raises(ParserException) { p.parse(tokens) } + end + + it "succeeds if the wrapped parser succeeds and the test passes" do + tokens = "testing".chars + expected_char = tokens[0] + test = ->(x : Char) { x == expected_char } + p = Assert.new(AnyToken(Char).new, test) + result = p.parse(tokens) + + result.value.should eq(expected_char) + test.call(expected_char).should be_true + end + end +end + +describe Satisfy do + describe "#parse" do + it "fails if there are input is empty" do + test = ->(x : Char) { x == '#' } # doesn't matter for this case + p = Satisfy(Char).new(test) + + expect_raises(ParserException) { p.parse([] of Char) } + end + + it "fails if the token fails the test" do + tokens = "testing".chars + test = ->(x : Char) { x == '#' } + p = Satisfy(Char).new(test) + + expect_raises(ParserException) { p.parse(tokens) } + end + + it "succeeds if the token passes the test" do + tokens = "testing".chars + expected_char = tokens[0] + test = ->(x : Char) { x == expected_char } + p = Satisfy(Char).new(test) + result = p.parse(tokens) + + result.value.should eq(expected_char) + test.call(result.value).should be_true + end + end +end + +describe Token do + describe "#parse" do + it "fails if the input is empty" do + expect_raises(ParserException) { Token(Char).new('t').parse([] of Char) } + end + + it "fails if the token is not the expected token" do + tokens = "testing".chars + p = Token(Char).new('#') + + expect_raises(ParserException) { p.parse(tokens) } + end + + it "succeeds if the token is the expected token" do + tokens = "testing".chars + expected_char = tokens[0] + p = Token(Char).new(expected_char) + result = p.parse(tokens) + + result.value.should eq(expected_char) + end + end +end + diff --git a/spec/spec_helper.cr b/spec/spec_helper.cr new file mode 100644 index 0000000..3a4747e --- /dev/null +++ b/spec/spec_helper.cr @@ -0,0 +1,2 @@ +require "spec" +require "../src/parcom" -- cgit v1.2.1