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