Skip to content

Commit

Permalink
✨ maybe combinator
Browse files Browse the repository at this point in the history
  • Loading branch information
nabeelvalley committed Jul 19, 2024
1 parent 94cf9f1 commit fff37e1
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 7 deletions.
13 changes: 11 additions & 2 deletions src/parz/combinators.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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))
}
}
}
26 changes: 21 additions & 5 deletions test/combinators_test.gleam
Original file line number Diff line number Diff line change
@@ -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}
Expand Down Expand Up @@ -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 =
Expand All @@ -169,20 +186,19 @@ 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)
}
})

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
Expand Down

0 comments on commit fff37e1

Please sign in to comment.