diff --git a/src/parz/combinators.gleam b/src/parz/combinators.gleam index 90bfe33..4b1eb40 100644 --- a/src/parz/combinators.gleam +++ b/src/parz/combinators.gleam @@ -135,6 +135,10 @@ pub fn map(parser: Parser(a), transform) { } } +pub fn map_token(parser: Parser(a), t) { + map(parser, fn(_) { t }) +} + pub fn try_map(parser: Parser(a), transform) { fn(input) { case parser(input) { diff --git a/test/combinators_test.gleam b/test/combinators_test.gleam index f5e40bb..250472d 100644 --- a/test/combinators_test.gleam +++ b/test/combinators_test.gleam @@ -2,9 +2,9 @@ import gleeunit/should import parz.{run} import parz/combinators.{ as_list, between, choice, concat_str, label_error, left, many, many1, map, - right, separator, separator1, sequence, + map_token, right, separator, separator1, sequence, try_map, } -import parz/parsers.{letters, str} +import parz/parsers.{letters, regex, str} import parz/types.{ParserState} pub fn left_test() { @@ -189,6 +189,54 @@ pub fn map_test() { |> should.be_error } +pub fn try_map_test() { + let error = "No content" + let parser = + between(str("["), regex("^[A-Za-z]*"), str("]")) + |> try_map(fn(ok) { + case ok { + "" -> Error(error) + content -> Ok(Content(content)) + } + }) + + run(parser, "[hello]") + |> should.be_ok + |> should.equal(ParserState(Content("hello"), "")) + + run(parser, "[hello]x") + |> should.be_ok + |> should.equal(ParserState(Content("hello"), "x")) + + run(parser, "[]x") + |> should.be_error + |> should.equal(error) + + run(parser, "[hellox") + |> should.be_error +} + +type Token { + Token +} + +pub fn map_token_test() { + let parser = + str("hello") + |> map_token(Token) + + run(parser, "hello") + |> should.be_ok + |> should.equal(ParserState(Token, "")) + + run(parser, "hellox") + |> should.be_ok + |> should.equal(ParserState(Token, "x")) + + run(parser, "xhello") + |> should.be_error +} + pub fn as_list_test() { let parser = as_list(str("x")) diff --git a/test/simple_parser_test.gleam b/test/simple_parser_test.gleam index 9566896..f468b35 100644 --- a/test/simple_parser_test.gleam +++ b/test/simple_parser_test.gleam @@ -1,7 +1,7 @@ import gleeunit/should import parz.{run} import parz/combinators.{ - choice, label_error, left, map, separator1, sequence, try_map, + choice, label_error, left, map, map_token, separator1, sequence, try_map, } import parz/parsers.{letters, regex, str} import parz/types.{ParserState} @@ -40,9 +40,9 @@ fn parser() { letters() |> map(Identifier) - let string_kind = str("string") |> map(fn(_) { StringKind }) - let number_kind = str("number") |> map(fn(_) { NumberKind }) - let boolean_kind = str("boolean") |> map(fn(_) { BooleanKind }) + let string_kind = str("string") |> map_token(StringKind) + let number_kind = str("number") |> map_token(NumberKind) + let boolean_kind = str("boolean") |> map_token(BooleanKind) let kind = choice([string_kind, number_kind, boolean_kind]) let node =