From fff37e16acbc74c4e2891039415afed4c656d882 Mon Sep 17 00:00:00 2001 From: Nabeel Valley <36758308+nabeelvalley@users.noreply.github.com> Date: Fri, 19 Jul 2024 22:13:12 +0200 Subject: [PATCH] :sparkles: maybe combinator --- src/parz/combinators.gleam | 13 +++++++++++-- test/combinators_test.gleam | 26 +++++++++++++++++++++----- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/parz/combinators.gleam b/src/parz/combinators.gleam index 849f168..36b9d6f 100644 --- a/src/parz/combinators.gleam +++ b/src/parz/combinators.gleam @@ -79,6 +79,15 @@ pub fn between(l: Parser, keep: Parser, r: Parser) -> Parser { } } +pub fn maybe(parser) { + fn(input) { + case parser(input) { + Ok(ok) -> Ok(ok) + Error(_) -> Ok(ParserState("", input)) + } + } +} + fn many_rec(parser: Parser, input, acc) { case parser(input) { Error(err) -> Error(err) @@ -129,11 +138,11 @@ pub fn label_error(parser, message) { } } -pub fn map(parser, transform) { +pub fn map(parser: Parser, transform) { fn(input) { case parser(input) { Error(err) -> Error(err) - Ok(ok) -> Ok(transform(ok)) + Ok(ok) -> Ok(#(transform(ok.matched), ok.remaining)) } } } diff --git a/test/combinators_test.gleam b/test/combinators_test.gleam index 4185cd9..fd4d1fa 100644 --- a/test/combinators_test.gleam +++ b/test/combinators_test.gleam @@ -1,7 +1,8 @@ import gleeunit/should import parz.{run} import parz/combinators.{ - between, choice, concat, label_error, left, many, many1, map, right, sequence, + between, choice, concat, label_error, left, many, many1, map, maybe, right, + sequence, } import parz/parsers.{letters, str} import parz/types.{ParserState} @@ -146,6 +147,22 @@ pub fn concat_test() { |> should.be_error } +pub fn maybe_test() { + let parser = maybe(str("x")) + + run(parser, "x") + |> should.be_ok + |> should.equal(ParserState("x", "")) + + run(parser, "!") + |> should.be_ok + |> should.equal(ParserState("", "!")) + + run(parser, "") + |> should.be_ok + |> should.equal(ParserState("", "")) +} + pub fn label_error_test() { let message = "Expected [letters]" let parser = @@ -169,8 +186,7 @@ pub fn map_test() { let parser = concat(sequence([str("["), letters(), str("]")])) |> map(fn(ok) { - let seq = ok.matched - case seq { + case ok { "" -> NoContent content -> Content(content) } @@ -178,11 +194,11 @@ pub fn map_test() { run(parser, "[hello]") |> should.be_ok - |> should.equal(Content("[hello]")) + |> should.equal(#(Content("[hello]"), "")) run(parser, "[hello]x") |> should.be_ok - |> should.equal(Content("[hello]")) + |> should.equal(#(Content("[hello]"), "x")) run(parser, "[hellox") |> should.be_error